segunda-feira, 22 de abril de 2013

Testing Afterburner.fx in a CRUD Application using JavaFX and FXML

It's been a few months without any new post on this blog :( I was preparing an application using Infinispan, NoSQL and JavaFX and unfortunately I lost my data in the disc... That would an epic post! In this post I'm going to show you a good old CRUD using FXML, JavaFX and the recent framework called Afterburner.fx, created by Adam Bien.

About Afterburner.fx

 Afterburner.fx is a minimalistic (2 classes) JavaFX MVP framework based on Convention over Configuration.
It's not me saying this, it's on afterburner.fx web page. What I can say I like the idea of this simple framework. I can say that it will not solve all issues, but it brings DI and the conventions saves  from writing repetitive code.

What is FXML?

It's a declarative way to build JavaFX interfaces using XML. FXMLs declare elements using XML and you can relate it to a controller that will handle the view for you. The controller can have the view elements injected where you will be able to retrieve fields' values or modify the view. It's a clean way to separate the view from the logic. You can read more about this in this article.

Write XML sucks, but don't in panic! FXML also offers a great tool to build the XML without having to write a single line of and I had the honor of being one of the first to blog about Scene Builder.

Server X Client

Our JavaFX client will be responsible to handle data in a server application which is built using JEE 6 technologies. We expose the CRUD functionalits using REST. It's a well known why to create remote applications. This same server will be used to create other ways to access the same CRUD functionality. Servlets, portlets, JAX-WS, Vaadin are the technologies that will be used in server too.
 In server everything is mavenized and we use JDF sample applications to build the maven structure of our server project.
The client also use Maven, but we have to refer to two local files: The JavaFX runtime and an afterburner.fx snapshot.

So... What's different in this new CRUD?

For me it's the first project I used FXML. I highlight the following points of why you should take a look at this project code:
  • It's a real-world application like because it uses JEE 6 and has server communication;
  • It uses afterburner.fx, an interesting project IMO;
  • The code need improvements :P
The application isn't visually attractive, but it allows the user to do all CRUD operation... see a few screenshot:




Conclusion

This is the first post of a series :) In other posts I'll show how to build it and talk a little about the code. One another post will be dedicated to show it accessing a rest service deployed in Openshift.

Ah, you want to see the code? OK, have it now

quarta-feira, 26 de setembro de 2012

Showing Object Properties in a TableView

This post is not to talk about any specific app but to show a simple How-To with TableView.
 Show values in a table in JavaFX is easy. You can show an object property with a few lines of code since we have classes that allows you to produce cells that read directly from the object. For example, let's say we have a class Person that contains two properties:
 

public class Person {
 private String name;
 private int id;
       //getters, setters..
}
If you want to create to columns to show the id and name properties, you need to create two columns and inform each column a PropertyValueFactory object instance:
TableView tableView = new TableView();
TableColumn idColumn = new TableColumn("Id");
idColumn.setCellValueFactory(new PropertyValueFactory("id"));
TableColumn nameColumn = new TableColumn("Name");
nameColumn.setCellValueFactory(new PropertyValueFactory("name"));
tableView.getColumns().addAll(idColumn, nameColumn);
Let's complicate a bit! What's if my object Person contains other object, for example, City and we want to show a City property? If we try to add a column for the property city with the following code:
 
TableColumn cityColumn = new TableColumn("City");
cityColumn.setCellValueFactory(new PropertyValueFactory("city"));

But it will not show any city property, it will actually show the toString method return:

Obviously you can go to City class code and override this method. Let't get the things a bit more complicated. This time let's say that you need to show a property from a City property, for example, State.

Person - City - State

Well, you can read things in the method toString of the object City, but this is not the best solution. One alternative is to set a CellValueFactory in your column using a Callback class.
. With this approach we can read any property we want from the Person class and return it to be showed in the table. It's pretty easy to use it:
TableColumn stateColumn = new TableColumn("State");
stateColumn.setCellValueFactory(new Callback, ObservableValue>() {    
    @Override    
    public ObservableValue call(CellDataFeatures c) {
        return new SimpleStringProperty(c.getValue().getCity().getState().getName());
    }
});

That's basically it what I wanted to show in this post. The entire test application code:

package org.jesuino.javafx.tableview.cellfactory;

import java.util.Arrays;
import java.util.List;

import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ObservableValue;
import javafx.scene.SceneBuilder;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TableColumn.CellDataFeatures;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.StackPaneBuilder;
import javafx.stage.Stage;
import javafx.util.Callback;

import org.jesuino.javafx.tableview.cellfactory.model.City;
import org.jesuino.javafx.tableview.cellfactory.model.Person;
import org.jesuino.javafx.tableview.cellfactory.model.State;

public class Main extends Application {

 TableView tableViewRef;

 public static void main(String[] args) {
  launch();
 }

 @Override
 public void start(Stage stage) throws Exception {

  stage.setScene(SceneBuilder
    .create()
    .width(420)
    .height(200)
    .root(StackPaneBuilder.create()
      .children(tableViewRef = createTableView()).build())
    .build());
  stage.setTitle("Testing Table View Cell Factory");
  stage.show();

  tableViewRef.getItems().addAll(mockPersonItems());
 }

 @SuppressWarnings("unchecked")
 private TableView createTableView() {
  TableView tableView = new TableView();

  TableColumn idColumn = new TableColumn(
    "Id");
  idColumn.setCellValueFactory(new PropertyValueFactory(
    "id"));
  idColumn.setMinWidth(80);

  TableColumn nameColumn = new TableColumn(
    "Name");
  nameColumn
    .setCellValueFactory(new PropertyValueFactory(
      "name"));
  nameColumn.setMinWidth(150);

  TableColumn cityColumn = new TableColumn(
    "City");
  cityColumn
    .setCellValueFactory(new PropertyValueFactory(
      "city"));
  cityColumn.setMinWidth(150);

  TableColumn stateColumn = new TableColumn(
    "State");
  stateColumn
    .setCellValueFactory(new Callback, ObservableValue>() {
     @Override
     public ObservableValue call(
       CellDataFeatures c) {
      return new SimpleStringProperty(c.getValue().getCity()
        .getState().getName());
     }
    });

  tableView.getColumns().addAll(idColumn, nameColumn, cityColumn,
    stateColumn);

  return tableView;
 }

 private List mockPersonItems() {
  State sp = new State("São Paulo", "SP");

  City saoJoseDosCampos = new City(sp, "São José dos Campos");
  City taubate = new City(sp, "Taubaté");
  City jacarei = new City(sp, "Jacareí");

  Person p1 = new Person("William Antônio Siqueira", 1, saoJoseDosCampos);
  Person p2 = new Person("Maria", 2, saoJoseDosCampos);
  Person p3 = new Person("João", 3, taubate);
  Person p4 = new Person("Joana", 4, jacarei);

  return Arrays.asList(p1, p2, p3, p4);
 }
}

quarta-feira, 4 de julho de 2012

TimaoFX: A simple JavaFX app

Yesterday I gave a talk about JavaFX to TDC Java University Track. The goal was to show JavaFX technology and motivate the attendees(which where about 40) to code something in JavaFX after the presentation. Coincidentally, yesterday was also the day of "Libertadores da América" finals, where Corinthians club were playing, but it never had won Libertadores. (but this time Corinthian did win the "Libertadores" \o/ )
Well, Corinthians has about 30 million fans in Brazil(even our former president is "Corintiano"), so I decided to create a very simple app to show some Corinthians information. The presentation is in Portuguese, but code is Universal :)
Introdução ao JavaFX
View more presentations from jesuinoPower

 As said, the app is very, very basic  and doesn't even makes database connection or access any WEB Services, the idea is show some JavaFX capabilities such as Multimedia and CSS and interface components(Controls).

The audience got impressed when I showed the CSS capabilities. With a few lines of CSS code I showed them how to change all the app's style.


The app code is in GitHub. It's a simple Eclipse project, all you have to do is clone the repository,  import the project into Eclipse, solve the jfxrt.jar dependency and then you can run the application.
Anyway, it was a such great experience give this talk to TDC and I'm looking forward to Saturday, when I'll give another JavaFX talk, but this time I will briefly show JavaFX basics to concentrate my efforts in JavaFX usage in real world apps .

terça-feira, 10 de abril de 2012

Fetching REST Data Sources with DataFX

DataFX is a project that helps you to show data in a JavaFX application from different sources of data in a few formats. You may read local data using the FileSource and this datasource may contain data in XML or CSV formats. I demonstrated how to use it in a previous post, today I want to quickly show you show to fetch data using the new RestRequestBuilder class.

RestRequestBuilder is very easy to use and with a few lines of code you will be able to fetch a JavaFX TableView from a remote XML, JSON or CSV source. As the name says, this class uses the builder way to create REST requests, which means that in a simple line of code you will have your request ready to fetch data in a TableView. Then you will simply have to inform to your datasource(as datasource you can understand a XMLDataSource or CSVDatasource).

Well, this post is very abstract so far, is time to use what we talked about in a program. To do that I want to present you a WEB Service I created a few years ago that allows to access information of our Brazilian Election Candidates using REST. The advantages of it is a centralized, "machine ready" and aggregated base of data, so will have one place to access using programatic ways and it will allow you to create Mashups and other applications (we need to be careful with politics in Brazil, we have a lot of corrupt politcs here :-(). The API is very simple to use and it was published in ProgrammableWeb, which is a site that has as objective put together all APIs(SOAP, REST or Javascript) and Mashups made with these APIs.

The main method of the API is the search. With three query parameters we can query all the base of data and bring the data in XML or JSON format. For example, the URI:

http://williamprogrammer.com/EleicoesAbertas/apiEleicoes/beta/2010/candidatos/busca?nome=ANT
Will bring all the candidates that has "ANT" in the name. The default format of the data offered by the API is XML. Additionally you can inform the page you are reading by using the parameter "pagina", but it's out of scope of this post. We will consume this source of data in JavaFX.

Now we know the target service to consume, we need to know how DataFX will help us to show these data. First, we can use RestRequestBuilder as follow:

NetworkSource ns = new RestRequestBuilder(
    "http://williamprogrammer.com")
    .path("EleicoesAbertas/apiEleicoes/beta/2010/candidatos/busca")
    .queryParam("nome", "ANT").build();
As the data is served in XML format, we need to chose which columns we will show in the TableView(I chose "nome", "nomeUrna", "estadoCivil", "resultadoEleicao", and "sexo") and the root element that contain the content to this columns(in our case it is "candidato"). The following code shows how can we retrieve this information.
XMLDataSource candidatosDataSource = new XMLDataSource(
    ns, "candidato", "nome", "nomeUrna",  "estadoCivil",
    "resultadoEleicao", "sexo");
By last we need to fill our TableView. It's pretty straightforward and described in my previous post. To finish here is our entire code and an image of the resulting JavaFX app.

package view;

import javafx.application.Application;
import javafx.scene.SceneBuilder;
import javafx.scene.control.TableView;
import javafx.stage.Stage;

import org.javafxdata.datasources.io.NetworkSource;
import org.javafxdata.datasources.io.RestRequestBuilder;
import org.javafxdata.datasources.protocol.XMLDataSource;

/**
 * 
 * @author jesuino
 * 
 */
public class Main extends Application {

 @SuppressWarnings("unchecked")
 @Override
 public void start(Stage stage) throws Exception {
  stage.setTitle("DataFX Test");
  // Just loading the URL and creating a Networkdatasource for it
  NetworkSource ns = new RestRequestBuilder(
    "http://williamprogrammer.com")
    .path("EleicoesAbertas/apiEleicoes/beta/2010/candidatos/busca")
    .queryParam("nome", "ANT").build();

  ns.setAccept("application/xml");
  XMLDataSource candidatosDataSource = new XMLDataSource(
    ns, "candidato", "nome", "nomeUrna", "estadoCivil",
    "resultadoEleicao", "sexo");
  @SuppressWarnings("rawtypes")
  TableView candidatos = new TableView();

  candidatos.getColumns().addAll(
    candidatosDataSource.getNamedColumn("nome"),
    candidatosDataSource.getNamedColumn("nomeUrna"),
    candidatosDataSource.getNamedColumn("estadoCivil"),
    candidatosDataSource.getNamedColumn("resultadoEleicao"),
    candidatosDataSource.getNamedColumn("sexo"));
  candidatos.setItems(candidatosDataSource);
  stage.setScene(SceneBuilder.create().root(candidatos).build());
  stage.show();
 }

 public static void main(String[] args) {
  Application.launch(args);
 }
}

AS you can see it's very easy to read a remote REST Datasource with DataFX and it will get better since it's an open source project. Of course you can use it in a more complex application, it's a simple demonstration.

terça-feira, 3 de abril de 2012

A First look at JavaFX Scene Builder Tool

It was just announced in JavaOne Japan that the JavaFX SceneBuilder Tool Beta is available for Download. Immediately I downloaded the tool and made a few tests and it's really a great tool. You should also try since it's available for Linux, Mac and Windows. The tool in entirely in JavaFX and you can preview the changes in a minute. In the following screenshot you can have a look of the appearance of the tool when you open it.
You can create application simply dragging and dropping the controls on left side to the center. Depending the control you selected you will be able to modify its properties on right side pane.
There are lines that help you positioning components and aligning them. It makes easy create well known layouts such as Form Layouts.
A cool and useful feature is the preview. You fan preview your application and there's no delay, the tool makes the preview immediately. Much better than spend time compiling and recompiling source code.
Finally you can export the page to a FXML file and use it in your application. The tool is amazing! It's been neither 1 hour it was released and I finished a simple application with it. Of course I noticed a few small bugs while using the new JavaFX app, but they are very small bugs if you consider that the tool is still in beta phase. Now JavaFX has all the keys to success: Open Source, easy, flexible, good tools, multi-platform, big and crescent community and, soon, multi-device, and me. Yeah, I'm back to have fun with JavaFX after a few months away.

segunda-feira, 30 de janeiro de 2012

A JavaFX App For The GateIn Navigation REST API

GateIn is a JBoss project that consists in a portal that goes beyond a simple portlet container. GateIn is the union of JBoss Portal and eXo Platform, so with GateIn you will have more than a JSR 168/286 implementation. Recently in the new GateIn 3.2, efforts for a public API has been done. The navigation REST API, for example, is complete in "read-only" part which means you can access all your page nodes and iterate through them. For more information about the GateIn REST API you can look at this article. To consume this API I decided to create a JavaFX application that would allow me to explore some of the new JavaFX features, like the cool embedded Browser and the TreeView control. In this post I want to show you this application, and try to share some of my experiences during the coding.

Consuming the GateIn Management API

To consume the Management API, specifically the navigation part, I created a separated Eclipse project, and was used the RESTEasy client API. To make the model part, I borrowed some classes from the project code. These classes are good, but I would like to have classes specifically to the navigation part, not the Management. So I used these classes to fill my NavigationNode class and have a higher abstraction level for the navigation.

The JavaFX app

The goal of the JavaFX app is to show the navigation tree and allows you to perform some actions for each node. The first action is log in the application, for this I created a class called "LoginPane". This class will take care the login part of the application and invoke the methods of the a LoginAction interface implementation. LoginAction is simple: contains two methods to be called by the LoginPane class. Below is the login pane in action.
The main part of the application consists of a TreeView and its context menu. An application menu was created just to perform simple actions like logout and refresh the tree.
Two more classes are used in this application : a simple modal dialog to show messages and a the SimpleWebView, which is used to open WEB pages.
I used a mix type of coding style with Builders and verbose Java. The Builders API from JavaFX is awesome, you can ease create classes using one line of code. A boring thing I faced during this application creation was the thread issues. It was used some asyncronous tasks (functional programming from JavaFX Script, I miss you =/ ) and then we got some "Not a JavaFX Thread" errors. I solved by using Platform.runLater. The bind was used one time, in the previous JavaFX Script I was addicted in binding, but now the form as bind is done, I'm not encouraged to use it, because now bind applies to *Property, which makes it more intrusive. You can see I'm not using the caspian default JavaFX style, I borrowed the CSS style from this post about JavaFX's CSS.

Conclusions

It's always great to explore a new REST API. RESTEasy went very well in giving a simple way more JAX-RS aware to access the API. JavaFX 2.0, as you know, is much better than the previous versions: faster and with a richer API and you can use Eclipse or your other favorite IDE to create JavaFX apps. This is not the end, I'll continue updating this application according the GateIn REST API evolution. You can check the JavaFX app or the client code in this repository on GitHub.

domingo, 22 de janeiro de 2012

Show data in JavaFX is made easy by DataFX project

A friend of mine, Teles Maciel, was scrapping a page that contains all the Islam formal prayers schedule for 2012 for who lives in São Paulo. He aims to create an app for mobile. While checking his sample XML I decided to use DataFX project to show these data, and I created an app in less than 5 minutes!

The DataFX project


It's divided in two main parts: Cell Factories and Data Sources and there is the RedFX integration.

Data Sources objective is to facilitate the access to XML/JDBC/CSV/JSON data and show in JavaFX. For example, you can read an XML file and visualize the data in a JavaFX table with a few lines of code.
Talking in code, you basically need to know the following Interfaces to use DataFX:

- DataSourceReader: Responsile for reading a source of data. Two classes that implements this interface are NetworkSource and FileSource;

- DataSource: Responsible for create the JavaFX(e.g. TableColumn, ObsevableLists) stuffs from the DataSourceReader. From this class, you can retrieve the items and the columns from the DataSourceReader. There's a Data Source implementation for each specific format, for example: XMLDataSource, ObjectDataSource, CSVDataSource and more sources are planned in future project releases.

If you want to know more about DataFX I recommend you to see the Jonathan Giles and Johan Vos presentation and read the API JavaDoc.

The "Salah Time" application


Let's start talking about this application showing the data we want to show:

 <?xml version="1.0" encoding="UTF-8"?>  
 <oracoes>  
 <oracao>  
 <nome>fajr</nome>  
 <dia>01/01</dia>  
 <horario tipo="verao">03:55</horario>  
 </oracao>  
 <oracao>  
 </oracao>  
 ...  
 </oracoes>  

As you can see, we have a pretty simple XML. The "horario"(time) tag has a "tipo"(type) attribute that may have two possible values: "verao"(summer, for daylight saving time) and "comum"(common, for common time). Imagine if you would show these data the first step would parse the data and then show according the toolkit/API you are using. For example, in JavaFX you would have to create a table and its columns. It is not hard, but a repetitive task when you just want to show the data or when you have a lot of files to show and that's when DataFX starts to help you.

The first thing I had to do was load my file using FileSource:

 FileSource fs = new FileSource("oracoes.xml");  

Then I created my XMLDataSource using this FileSource, the tag name ("oracao") and the columns I want to retrieve from oracao: nome, dia and horario. Here is the code (yes, one line):

 XMLDataSource<String[], Object> salatDataSource = new XMLDataSource<String[], Object>(  
 fs, "oracao", "nome", "dia", "horario");  

Now the last step is simply integrate XMLDataSource with a TableView. I just had to retrieve the columns I want and add it to my TableView and the items is the DataSource itself:


 package org.salattime.main;  
 import javafx.application.Application;  
 import javafx.scene.SceneBuilder;  
 import javafx.scene.control.TableColumn;  
 import javafx.scene.control.TableView;  
 import javafx.stage.Stage;  
 import org.javafxdata.datasources.io.FileSource;  
 import org.javafxdata.datasources.protocol.XMLDataSource;  
 /**  
  *   
  * So, I want to read the data from oracoes.xml and show in a table. This class  
  * will do it  
  *   
  * @author jesuino  
  *   
  */  
 public class Main extends Application {  
      @SuppressWarnings("unchecked")  
      @Override  
      public void start(Stage stage) throws Exception {  
           stage.setTitle("Salats do ano de 2012");  
           // Just loading the file...  
           FileSource fs = new FileSource("oracoes.xml");  
           // Now creating my datasource, I just need to inform my columns and  
           // oracao, because it is the root of the columns I want  
           XMLDataSource<String[], Object> salatDataSource = new XMLDataSource<String[], Object>(  
                     fs, "oracao", "nome", "dia", "horario");  
           @SuppressWarnings("rawtypes")  
           TableView salats = new TableView();  
           TableColumn<?, ?> nomeCol = salatDataSource.getNamedColumn("nome");  
           TableColumn<?, ?> diaCol = salatDataSource.getNamedColumn("dia");  
           TableColumn<?, ?> horarioCol = salatDataSource  
                     .getNamedColumn("horario");  
           salats.getColumns().addAll(nomeCol, diaCol, horarioCol);  
           salats.setItems(salatDataSource);  
           stage.setScene(SceneBuilder.create().root(salats).build());  
           stage.show();  
      }  
      public static void main(String[] args) {  
           Application.launch(args);  
      }  
 }  

Here is the result:



Further use of DataFX(the DataSource part)


This sample seems very simple, but here are some uses for DataFX you may consider:

- Visualization of a REST API result using the NetworkSource;
- Help you to show data in multiple formats with a small portion of code with FileSource and the currently available DataSources implementations (more will come in a future);
- In future, read data from database with a JDBC DataSource;


Remember this project is just getting started, there are more to come :-)