Build a JavaFX + LeapMotion application with gradle

For SlideshowFX (which is an app I’m developing in JavaFX and using the LeapMotion controller) I am trying to use gradle as build and dependencies management system instead of the very well-known  maven. There are few steps I had to fight with to successfully build a self-contained application (aka native bundle). For those don’t knowing what that means take a look at the Oracle Documentation.

Disclaimer : I’m new in the gradle’s world so maybe a lot of things could be improved.

Prerequisites

  • Having a JDK 8 up and running
  • Having the JAVA_HOME environment variable defined to point the the JDK 8 installation
  • Having gradle installed properly (version 1.11 used at the time this article was written)
  • Knowing gradle a little bit

 

The javafxpackager

In order to package a JavaFX application you can use the javafxpackager tool provided with the JDK. It allows you to create the application JAR and then the native bundle for your application.

To create the jar you will use the following command:

javafxpackager -createjar ...

You will also need to define some attributes according your application, like -classpath for the list of JARs and libraries your application is using, -appclass for indicating what is the Application class of your application, -srcdir and -srcfiles for indicating which files should be included in your JAR, -outdir for indicating where the JAR file will be created and -outfile for the name of the JAR file.

To create the native bundle you will use the following command:

javafxpackager -deploy -native ...

Building with gradle

In order to build your application with gradle, we will invoke the javafxpackager tool from gradle itself. A JavaFX plugin for gradle exists but I didn’t succeed in using it for my purpose. Indeed for LeapMotion you need some DLL and dylib files that weren’t included in the final JavaFX bundle so I decided to do it myself using gradle tasks. And this also allowed to have a better understanding of the javafxpackager tool instead of just using an IDE to generate my bundle.

Configuration

In the build.gradle file, I configured all projects with the Java plugin and the source and target compatibility:

subprojects {
  apply plugin: 'java'
  sourceCompatibility = 1.8
  targetCompatibility= 1.8
}

Dependencies and libraries

For SlideshowFX I decided to use file dependencies. So first of all I declared the dependencies at the beginning of the build.gradle file:

ext {
  allLibs = new File(rootDir, '/lib')
  felix = fileTree(dir: allLibs, include: 'Felix/*.jar')
  json = fileTree(dir: allLibs, include: 'json/*.jar')
  jsoup = fileTree(dir: allLibs, include: 'jsoup-1.7.3.jar')
  junit = fileTree(dir: allLibs, include: 'junit-4.11.jar')
  leapmotion = fileTree(dir: allLibs, include: 'Leap/*')
  markdown = fileTree(dir: allLibs, include: 'markdown/*.jar')
  scribe = fileTree(dir: allLibs, include: 'Scribe/*.jar')
  textile = fileTree(dir: allLibs, include: 'WikiText/*.jar')
  velocity = fileTree(dir: allLibs, include: 'Velocity/*.jar')
  vertx = fileTree(dir: allLibs, include: 'Vert.x/*.jar')
  zxing = fileTree(dir: allLibs, include: 'ZXing/*.jar')

  jdk = System.env.'JAVA_HOME'
}

Those files collections will be used further for declaring dependencies for each project. For LeapMotion, all files are included: JARs, DLL, and dylib.

Build the jar

To build the JAR I decided to overwrite the default JAR task present in the Java plugin of gradle. We are going to follow these steps:

  • Copy all dependencies of the project to the libsDir folder
  • Build the -classpath attribute for the javafxpackager tool. Each JAR used by the application is adde to the classpath
  • Build the -srcdir/-srcfiles attributes for the javafxpackager tool. There will be many of these attributes because there are classes and resources
  • Build the javafxpackager command to execute
  • Execute the command

Knowing that here is the task definition:

task jar(overwrite: true) << {

  if (jdk != null && !jdk.isEmpty()) {

    if(!libsDir.exists()) libsDir.mkdirs()

    // Copying libs
    copy {
      from(new File(project(':SlideshowFX-markup').libsDir, project(':SlideshowFX-markup').archivesBaseName + ".jar"))
      from(felix.files)
      from(json.files)
      from(jsoup.files)
      from(leapmotion.files)
      from(scribe.files)
      from(velocity.files)
      from(vertx.files)
      from(zxing.files)

      into(libsDir)
    }

    def classpath = ""

    fileTree(dir: libsDir, include: '*.jar', exclude: archivesBaseName + ".jar").each {
      f ->
      classpath += f.name + ","
    }

    classpath += "."

    def javafxpackager = exec {
      workingDir "${project.projectDir.absolutePath}"

      commandLine "${jdk}/bin/javafxpackager",
                  "-createjar", "-v",
                  "-appclass", "com.twasyl.slideshowfx.app.SlideshowFX",
                  "-classpath", "${classpath}",
                  "-outdir", "${buildDir}${File.separator}${libsDir.name}",
                  "-outfile", "${project.archivesBaseName}",
                  "-srcdir", "${buildDir.name}/classes/main", "-srcfiles", "com",
                  "-srcdir", "${buildDir.name}/resources/main", "-srcfiles", "com"
    }
  }
}

Build the native bundle

Now that we have the JAR, let’s make the native bundle. For this we will also create a task for achieving this.

task buildJavaFXBundle << {

  if (jdk != null && !jdk.isEmpty()) {

    def javafxpackager = exec {
      workingDir "${project.projectDir.absolutePath}"

      commandLine "${jdk}/bin/javafxpackager",
                  "-deploy",
                  "-native",
                  "-name", "SlideshowFX",
                  "-outdir", "${buildDir.name}${File.separator}dist",
                  "-outfile", "SlideshowFX",
                  "-srcdir", "${buildDir.name}${File.separator}${libsDir.name}",
                  "-appclass", "com.twasyl.slideshowfx.app.SlideshowFX"
    }
  }
}

Tasks’ dependencies

Now that we have the needed tasks, let’s add some dependencies between them in order to include everything in the gradle lifecycle:

tasks['jar'].dependsOn 'classes'
tasks['jar'].dependsOn ':SlideshowFX-markup:jar'
tasks['buildJavaFXBundle'].dependsOn 'jar'
tasks['assemble'].dependsOn 'buildJavaFXBundle'

Now calling the assemble task makes it.

Advertisements

Partial HTML generation from textile using eclipse Mylyn standalone

The title is pretty much explicit. For SlideshowFX, I needed to generate HTML content from textile, in order to define slide’s content. Looking for a lib, I found eclipse Mylyn that can be used in a standalone way. The library is pretty powerful but I have to look a lot at the sources in order to get the things done how I wanted to (#LukeAtTheSource power). Generally to convert a markup string into a HTML one, you create a MarkupLanguage as well as a MarkupParser and do the following:

final MarkupLanguage language = new TextileLanguage();
final MarkupParser parser = new MarkupParser(language);
parser.parseToHTML("h1. My little String");

The thing is that this code will create a whole HTML document (with html, head, body and so on tags). Me needs were to just get the HTML code corresponding to my string, e.g.

<h1>My little String</h1>

So the code should be changed to use a DocumentBuilder, like the following one:

final StringWriter writer = new StringWriter();
final DocumentBuilder builder = new HtmlDocumentBuilder(writer);
final MarkupLanguage language = new TextileLanguage();
final MarkupParser parser = new MarkupParser(language, builder);

// false indicates to not produce a whole HTML document
parser.parse("h1. My little String", false);

writer.flush();
writer.close();

String htmlContent = writer.toString();

This is almost done except that Mylyn generates IDs (which is kind of normal right?) by using the content of the markup. In short, I wanted to avoid IDs’ generation but I could’t find a right and efficient way to do it. So I decided to ensure uniqueness of IDs by always getting the current timestamp. Maybe it’s not a wonderful solution, but for the purpose of this little tutorial it will be perfect. The main idea is to change the ID generation and for doing this, you have to override some classes, because the default ID generation strategy is stored as a static and final variable, and no setters are available. The following example demonstrates how to do it:

final StringWriter writer = new StringWriter();

// The generation strategy generates IDs using the current timestamp
final IdGenerationStrategy idGenerationStrategy = new IdGenerationStrategy() {
  @Override
  public String generateId(String s) {
    return System.currentTimeMillis() + "";
  }
};

final IdGenerator idGenerator = new IdGenerator();
idGenerator.setGenerationStrategy(idGenerationStrategy);

final TextileContentState contentState = new TextileContentState() {
  @Override
  public IdGenerator getIdGenerator() {
    return idGenerator;
  }
};

// Override the language to return the created contentState used for the ID generation
final MarkupLanguage language = new TextileLanguage() {
  @Override
  protected ContentState createState() {
    return contentState;
  }
};

final DocumentBuilder builder = new HtmlDocumentBuilder(writer);

final MarkupParser parser = new MarkupParser(language, builder);

parser.parse(markupString, false);

writer.flush();
writer.close();

final String htmlContent = writer.toString();

This is it. Enjoy.

TweetWallFX – Part 1

Hi,

It has been a while since I posted something on here. I think that everyone has heard about JavaFX and its recent updates. I had the chance to assist at the JavaFX session done by Nicolas Lorain, Jean-François Denise and Eric Le Ponner (working at Oracle) at Devoxx France in April 2012 and then to talk to these guys. What a great meeting, such interesting people and such a promising technology. Well maybe you’re already familiar with JavaFX 1.3, or maybe like me you’ve looked at it and didn’t want to learn some another new scripting language. Personally JavaFX 1 wasn’t interesting for me for the simple reason that it wasn’t possible to use external JARs file, like a JDBC driver. But now, all of this goes away because JavaFX 2.1 has been released (you can download it here) and I really have to admit: I’m confident about it. Because I wanted to start learning this new technology I decided to create an application build with JFX. So I decided to create a tweet wall application and share with you my experiences, my learnings and my enthusiasm. Well, the functionality of the application is to basically display tweets with a specific hashtag. So pretty straight forward. Currently the application is far away not finished and that’s the reason why there will be more posts about it.

Ok, let’s go …

Swing is dead !! Long live JFX

Until now, we have to admit that building desktop applications in Java was pretty hard. Swing is currently an old technology, even if it still works well. But developing in Swing is pretty long and you can not use it to do some rad (rapid application development) in order to quickly have a poc (proof of concept) of the UI (user interface). In Swing I usually had two mains problems:

  • 1. Positioning: it was terribly awful to get a correct UI with your components placed where you want to, reacting correctly when the window’s size changed and so on
  • 2. EDT: the Event Dispatch Thread was typically hard to manipulate, especially when you were using some custom painting! (Do you remember how many times you tried to understand which repaint() method you had to call? On which component?)

Now this is said, let’s focus a bit on JavaFX. JFX 2 introduced FXML which is a scriptable, XML-based markup language. It is used to create your graph of objects in order to build your UI. It is the same concept that Microsoft used in WPF called XAML. So maybe you’re wondering what a graph of objects is. If you’re familiar with the JSF technology, you probably know about the concept UI View, that contains all components displayed in your JSF pages. Well FXML is globally the same concept: you put all components (that have a “representation” in FXML) of your UI in a XML file. Like JSF pages, you can also use the Expression Language (EL) in your FXML markups, as well as some JavaScript scripts. And what is very interesting is that you can use some CSS properties on your components in order to create an attractive UI. Finally one important thing to say is that you can bind components of your FXML file to a component in a backing bean for various reasons and I will explain some of them in time. As you can see, all of these concepts are not really new in our Java world, you just have to take a look at JSF.

Also, what is very important about FXML is that for the first time in Java desktop application we can do real MVC. Indeed, just let be honest: how did you do real MVC in Swing? Yeah you created a package for your graphical components, another one for your listeners and so one. And because sometimes we were so lazy we mixed the listeners classes in the components classes… Well forget about that. With FXML you can completely separate the view layer from the controller.

Start screen

After this brief introduction, let’s see the first screen we’re going to create for our application: a start screen allowing us to specify which hashtag to create a “wall” for it. For now we’re going to use these “visible” components:

  • A label for displaying to enter a hashtag
  • A text field for entering the hashtag
  • A search button

Well, after creating a new JavaFX project in your favorite IDE (I currently use NetBeans) you will have a main class launching the application and a FXML file. We are going to modify this file in order to create a UI for that screen.

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

<?import java.lang.*?>
<?import javafx.scene.*?>
<?import javafx.scene.effect.*?>
<?import javafx.scene.image.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<AnchorPane id="mainPanel" fx:id="anchorPane" prefHeight="768" prefWidth="1024" xmlns:fx="http://javafx.com/fxml" fx:controller="com.twasyl.tweetwallfx.controllers.TweetWallFXController">
    <children>
        <TabPane id="tabPane" fx:id="tabPane" >
            <tabs>
                <Tab closable="false">
                    <text>Start</text>
                    <content>
                        <VBox fx:id="searchForm" alignment="CENTER" spacing="10" prefHeight="768" prefWidth="1024">
                            <children>
                                <HBox alignment="CENTER">
                                    <children>
                                        <Label id="hashtagLabel" text="Enter the hashtag to look for: "/>
                                        <TextField id="hashtagTextField" fx:id="hashtagTextField" promptText="#" prefWidth="200" />  
                                    </children>
                                </HBox>
                                <Button id="button" text="Search" onAction="#startTweetWall"  />
                            </children>
                        </VBox>
                    </content>
                </Tab>
            </tabs>
        </TabPane>
    </children>
</AnchorPane>

Well let’s get some explanations. You can see that the root element of the document is which is a region into which you can add multiple components. The markup has several attributes that are pretty easy understand except maybe the fx:controller. This tag has a value which is a FQCN (full qualified class name). This attribute allows you to bind your current FXML file to a backing class that will be use as controller. And what is a controller? It is a class that can contain methods that will be called when a button is pressed for example, or a binding to some components of you FXML file to a class. I’m sure you’re wondering how the binding is done. Well it is done using the fx:id which value must be strictly equal to the name of a component in your backing class, annotated with @FXML. Example: my AnchorPane here has th fx:id=”anchorPane”. So in my class defined by the fx:controller attribue I have this:

public class TweetWallFXController implements Initializable {

    @FXML
    private TabPane tabPane;
    @FXML
    private TextField hashtagTextField;
    @FXML
    private Pane anchorPane;

    @FXML
    private void startTweetWall(ActionEvent event) {
        // ...
    }

    @Override
    public void initialize(URL arg0, ResourceBundle arg1) {
    }
}

The I use a TabPane with some tabs. And the first tab contains some layout components (VBox, HBox) used to place my Label, TextField and Button on the screen. What I would like to explain is the onAction attribute of my Button. Indeed the value is #startTweetWall which refers to a method named startTweetWall annotated with @FXML in my controller class (defined in the fx:controller attribute of my AnchorPane). The # indicates you’re referring a method. Well this FXML gives you this screen:

Not very beautiful… Let’s just modify our components by adding some style.

<HBox alignment="CENTER">
  <children>
    <Label id="hashtagLabel" text="Enter the hashtag to look for: " style="-fx-font-size: 25pt;"/>
    <TextField id="hashtagTextField" fx:id="hashtagTextField" promptText="#" prefWidth="200" style="-fx-font-size: 20pt;" />
  </children>
</HBox>
<Button id="button" text="Search" onAction="#startTweetWall" style="-fx-font-size: 20pt;" />

As you can see, every style property used by JFX is prefixed by -fx-. And these modifications give us this screen:

Now, why not adding some background gradient? Let’s go! I surround my components by another AnchorPane.

...
<AnchorPane style="-fx-background-color: linear-gradient(#69B4E4 0%, #0070B9 100%);">
  <VBox fx:id="searchForm" alignment="CENTER" spacing="10" prefHeight="768" prefWidth="1024">
    <children>
      <HBox alignment="CENTER">
        <children>
          <Label id="hashtagLabel" text="Enter the hashtag to look for: " style="-fx-font-size: 25pt;" />
          <TextField id="hashtagTextField" fx:id="hashtagTextField" promptText="#" prefWidth="200" style="-fx-font-size: 20pt;" />  
        </children>
      </HBox>
      <Button id="button" text="Search" onAction="#startTweetWall" style="-fx-font-size: 20pt;" />
    </children>
  </VBox>
</AnchorPane>
...

Look at the -fx-background-color style. You can use a function named linear-gradient and pass to it any number of colors you want your gradient to be composed of! The percentage is where the color begins or ends (depending if it is the first argument).

Looks better. Let’s add an icon (users love icons).

...
<AnchorPane style="-fx-background-color: linear-gradient(#69B4E4 0%, #0070B9 100%);">
  <ImageView id="twitterSticker" fitWidth="128" fitHeight="128" layoutX="30" layoutY="30">
    <image>
      <Image url="@/com/twasyl/tweetwallfx/resources/images/twitterSticker.png" />
    </image> 
  </ImageView>
  <VBox fx:id="searchForm" alignment="CENTER" spacing="10" prefHeight="768" prefWidth="1024">
    ...
  </VBox>
</AnchorPane>

We’re using an ImageView placed at 30px from the top and left corner, with a size of 128px. You specify the image by using the Image markup to indicates which image you would like to load using the url attribute. Starting the value value with a @ means that the image location is not relative to the current location of the FXML file.

And now, the name of the application.

...
<ImageView id="twitterSticker" fitWidth="128" fitHeight="128" x="30" layoutY="30">
  ...
</ImageView>
<Label text="TweetWallFX" prefWidth="1024" style="-fx-font-size: 100pt; -fx-text-fill: white; -fx-font-weight: bold;" alignment="CENTER" layoutY="30" />
...

Don’t you think this title is a bit “simple”? Well let’s add some effects really simply!!

...
<Label text="TweetWallFX" prefWidth="1024" style="-fx-font-size: 100pt; -fx-text-fill: white; -fx-font-weight: bold;" alignment="CENTER" layoutY="30">
  <effect>
    <DropShadow offsetY="5" offsetX="5" color="GRAY">
      <input>
        <Reflection fraction="0.7" topOffset="-20" />
      </input>
    </DropShadow>
  </effect>
</Label>
...

As you can see, we use the effect markup in order to add one effect to the label. If you want to add more effects, some have an input in order to chain effects. That is the reason why you first create the DropShadow effect that contains the Reflection one. And the final result is:

Well that’s it for this post. As you can see, everything that has been done uses FXML. No other code!! You can see how powerful and convenient FXML is. And the best way to know how to use it is to read the documentation, which contains plenty of information!

Stay tuned for next part !!

Get annotation’s field’s value easily

Hello,

Maybe have you ever been confronted to the problem of getting the value of a field of an annotation. You see what I’m talking about? No. Example:

@Foo(myField="Hello there")
public class FooClass implements Serializable {
// ...
}

Let’s imagine you want to retrieve the value of myField (ie Hello there). How could You do that? Let me propose you two ways.

First way
The easier way but absolutely not scalable is to do the following code:

// ...
String myFieldValue = "Hello there";
// ...

Well it’s working, isn’t it? But imagine you have to get this value a lot of times, in different classes and so on … Are you going to use your favorite IDE’s function “Find and replace …”? Why not. But, lets take a look to a different way.

Second way
The other solution, much more scalable, is to use reflexivity. And the great thing about that is that you will be able to use for whatever annotation and whatever field. Lets take a look at this:

public String getClassAnnotationValue(Class classType, Class annotationType, String attributeName) {
        String value = null;

        Annotation annotation = classType.getAnnotation(annotationType);
        if (annotation != null) {
            try {
                value = (String) annotation.annotationType().getMethod(attributeName).invoke(annotation);
            } catch (Exception ex) {
            }
        }

        return value;
    }

How invoke that snippet of code?

// ...
String myFieldValue = getClassAnnotationValue(FooClass.class, Foo.class, "myField");
// ...

As you can see, you can use it for whatever class annotation on a class. You can now imagine doing the same for a field Annotation. Give it a try!

This is a pretty useful when you work in JEE. Imagine a SessionBean with may implementations, or an EntityBean with the @Table annotation, or a simple field with the @Column annotation. And these two last examples, it is useful if you build your own SQL queries. Because with this snippet of code, you won’t have to look everywhere you use your EntityBean and change the table name in your query …

Well, I hope this could help you sometimes.
Enjoy.

Deal with Context-Path in Java EE

Maybe have you ever try to create an Enterprise Application in Java, containing both EJB and Web modules. And maybe have you noticed that the context-path of the web application is the same that the generated WAR file.
So let’s imagine you create an enterprise application named JustMyApp with two modules: JustMyApp-ejb and JustMyApp-war. After deploying your application, you just go to your website using an URL like this one (depending on which port your server is running): http://localhost:8080/JustMyApp-war. Well I have to admit I totally dislike to enter -war in the URL… Why not JustMyApp only?

Context-Path in Java EE is kind of strange. Indeed, if you only have a WAR (not en EAR) changing the CP for the WAR is working fine. But if you are in an EAR, things are little bit different!

So how to do that? You have to create a file called a Standard Deployment Descriptor and put it into your EAR. The name of this file must be application.xml. This file contains the name of all modules you have in the EAR, and you can specify the context-path for your Web module. Let’s see an example:

<?xml version="1.0" encoding="UTF-8"?>
<application version="6" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/application_6.xsd">
  <display-name>JustMyApp</display-name>
  <module>
    <ejb>JustMyApp-ejb.jar</ejb>
  </module>
  <module>
    <web>
      <web-uri>JustMyApp-war.war</web-uri>
      <context-root>/JustMyApp</context-root>
    </web>
  </module>
</application>

The URL to enter to access your web application is just specified by the <context-root>…</context-root> markup. So put there whatever you want and just try it ! That’s how the Context-Path for EAR can be changed !

Enjoy.

Deploy Java applications on Mac

Hello,

You need to deploy Java applications on Mac? Take a look at : http://thierry.wasylczenko.free.fr/?p=108

Enjoy.

Maximize a JFrame

Hello everyone,

I’m writing a new post because I saw an awfull code to maximize a JFrame in Java. Maybe You’ve ever tried to maximize Your GUI at the startup of Your application. It’s something which is very basic but which can be done in several ways (and some awfull ways too…).

First of all, You could retrieve the size of Your screen, and set it to Your JFrame like this :

// Get the screen size
Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
// Create a jframe, just for the example
JFrame myFrame = new JFrame();
// Set the size
myFrame.setPreferredSize(screen);
myFrame.setVisible(true);

Well this is bad… Why? Because imagine You created Your application on Linux, and then try to launch it on Windows (I test an application recently…). On Linux, fine. On Windows, the application was under the task bar… So a part of the application was hidden… And the developpers used a similar code. So, this is not really a good practice.
There is a much simplier and efficient way to do that. Just look at this :

JFrame myFrame = new JFrame();
myFrame.setVisible(true);
myFrame.setExtendedState(JFrame.MAXIMIZED_BOTH);

That’s all ! Much more simplier and better working. Notice that setting the state is after making the frame visible 🙂