quarta-feira, 18 de outubro de 2017

JavaFX with Bean Validation and CDI 2.0

When JavaFX 2 was released I remember people looking for frameworks that would make easy to integrate JavaFX with a validation framework, a dependency injection container and other enterprise services. Currently we can integrate CDI 2.0 and Bean Validation 2.0 with a JavaFX application without the need of any external framework. In this post I will show you how to validate your javaFX screen fields using bean validation in a CDI managed application.

Before talking about all these things and JavaFX I recommend you to check the following posts from this blog:

Validating JavaFX controls using Bean Validation

With Bean Validation 2.0 we have the automatic unwrap of JavaFX properties. Which means that if you have a field that is of type of ObservableValue so the validator implementation will be able to retrieve the actual value to perform the validation. However, JavaFX control fields are still not supported, so if you try something like the code below you will have an exception when running the validator against your JavaFX controller:  

This happens because the validator implementation doesn't know how to retrieve values from a JavaFX controller. What we need to do is create a class that implements javax.validation.valueextraction.ValueExtractor. We must use the control type in this class and implement a method that will do the actual value extraction and use the annotation javax.validation.valueextraction.ExtractedValue to set the value type that will be extracted (String, Integer, LocalDate...). To avoid additional steps we use the annotation javax.validation.valueextraction.UnwrapByDefault on our implementation. This is what ValueExtractor for TextField and for DatePicker looks like:

Value Extractor for DatePicket

Value Extractor for TextField

Finally we must register it in within the bean validation framework. There are a couple of ways of doing it, we chose the SPI way, which is create a file named META-INF/services/javax.validation.valueextraction.ValueExtractor with the class name of our ValueExtractors:

Content of file META-INF/services/javax.validation.valueextraction.ValueExtractor

We could have a bean validation extension for JavaFX that should include all the extractors possible for the JavaFX controls. Let me know ff you are doing something like that and I can mention it here!

Showing validation errors to users

You will probably want to show users messages when the value they entered for the fields are not valid. Once you have access to the Validator class in your controller you can simply call validate against your controller itself and set labels values in the view to show users messages. I personally don't like this approach because I think it is intrusive. An easy solution is displaying a tooltip and to do so we must have access to the control which value is invalid. The following code did this in our test application:

Method showValidationErrors gets the control that has an invalid value and set a tooltip for it

To show the tooltip we must have access to the control itself, and to do this we have to make some reflection, hence the field representing the control should be public or make get methods to access it

CDI, Bean Validation and JavaFX

There's nothing to add about CDI from what I have mentioned in Using CDI 2.0 in a JavaFX application post. I just wanted to share that the Hibernate Validator CDI API worked on a JavaFX application and due this I can simply inject the validator on my controller class! A single dependency will make that possible: org.hibernate.validator:hibernate-validator-cdi. See below the application files:

Our maven project and its files

And these are the dependencies I added to pom.xml:

These are all dependencies required to use bean validation and CDI on a JavaFX application

Code of a sample application can be found in github. Below you can see a quick video I made just to show what the validation with tooltips looks like:

Why this is important

Being able to integrate with Java EE (or should I say EE4J already?) is a key feature for users who want to build real world applications with JavaFX, it will bring persistence, validation, injection and more. The main question that remains here is: will it work on a Android application that uses Gluon/ JavaFX Ports?

For more Bean Validation specific examples you may check this Hendrik Ebbers pull request to hibernate validator project.

segunda-feira, 16 de outubro de 2017

Testing Bean Validation 2.0

Bean Validation 2.0 is among all the new Java EE 8 good new features:

In this post I will share a sample application I used to see in action the following Bean Validation 2.0 features:

  •  List items validation
  • Temporal validation using Java 8

Project setup

Hibernate Validator is the RI for Bean Validation 2.0 and the project, being a maven or gradle project, must use the following dependencies (or later versions): org.hibernate:hibernate-validator:6.0.2.Final and you should also add org.glassfish:javax.el:3.0.1-X as a hibernate validator dependency, where X is the build, check the maven repository for more. This is what my pom.xml looks like:

Using bean validation annotations in a bean fields

To test the new annotations I used the following bean:

Notice the new annotations in subscribers and in manufactureDate and expirationDate fields:

  • subscribers: I am validating users emails, all the Strings added to this list should be an email. To do this a simple @Email annotation solved the problem;
  • manufactureDate: The validation is to make sure that the manufactureDate is a past date and to do so a single @Past annotation will make sure that this is correctly validated;
  • expirationDate: The product should expire in future and the @Future annotation solves everything.

Finally I can test this in a main class, see:

When running this only p4 will be valid:

The code is in my github. Feel free to clone it and make more tests on top of this project.

terça-feira, 10 de outubro de 2017

Using CDI 2.0 in a JavaFX application

With the CDI 2.0 release we have a container that can be used in Java SE applications! Previously if you wanted to make use of CDI 1.x in a Java SE application you had to use Weld classes, see FXML & JavaFX—Fueled by CDI & JBoss Weld post.

Adam Bien introduced the SE container in a video, see:

Of course I had to try it with JavaFX so I can use CDI in some personal applications!

Create the Container in a JavaFX Application

By JavaFX application I mean the class that extends javafx.application.Application, which is the entry point for JavaFX apps and where the main stage can be used. To use CDI we should create the SeContainer and make sure that it create all classes managed by CDI. This should be done in the entry point Application class so we manage all the classes created from there.

Once you started the container you have different ways to send the initial stage to the actual Application class, for example, you can have users to implement an interface and then use the CDI container to select a bean that implements the interface, for example:

There's a more elegant way which is by using CDI Observer API. In this case we may create an annotation that will be the qualifier for the event javafx.stage.Stage. CDI will wisely know all classes that observes that event and will select the user classes when we fire it by sending the primary stage. This is similar to what was done in FXML & JavaFX—Fueled by CDI & JBoss Weld post:

Whatever approach you chose, just make sure to not shutdown the container or it may bring inconsistencies (actually I think it will work in most of the cases, but I decided to not shutdown it).

Ok, now you can use CDI in your application! Go ahead and inject stuff in your class. Unless of course if you are using FXML and in this case FXML will create the controllers for you using reflection, and CDI won't work there, unless we use CDI itself to produce a FXMLLoader instance and in this case we can set a callback to create the bean using CDI, so all the injected fields won't be null. The code was taken from  FXML & JavaFX—Fueled by CDI & JBoss Weld post because it didn't have change at all, we are just using Java 8 delicious lambdas,  see:

Finally you can create your own app, but never call FXMLLoader static methods when using CDI, instead, use the injected one:

Remember that you are also able to inject stuff in your controller. In my case I injected a classic Greeter to the controller:

Also, since this a CDI application we should not forget about the empty beans.xml file. This is the structure of the project I used in my tests:

This is the final result with the fact that now the message is coming from a CDI Bean:

The full project can be found in my github.

segunda-feira, 18 de setembro de 2017

How Apache Tika helped me to extract open data from random files

I love open data. Recently we had the idea to see if alderman were attending the legislative sessions, when getting into the town website we had the bad news that each session information was provided in a PDF or XLS file that should be downloaded. That was really bad and we thought that we should do something.
Sessão means session, behind each session we had a link to the file that contains the session information...

Our first goal was to download all the files so we could parse it later, a simple bash script solved that, but then we had the challenge to read all files and transform it to javascript so we could show it in a web page.
Well, we thought: for PDF we use iText, for XLS we use JExcel. Issue solved? No.

Read the file to text would require more work, specially with the JExcel API, that allow us to go thought the spreadsheet cells, read the text of each cell etc. But that was fine, that is the exciting parts about dealing with open data: hacking. We even used Strategy design pattern, how cool is that?

Strategy, but in our case the Strategy was the parse method and the concrete classes were XLSParser and PDFParser. Image source.

However... Yes, you guessed it, the spreadsheets were not regular, so we could no easily guess which cells had the information we were looking for. I would stop there because TBH this kind of voluntary of work is not something that will bring you money neither recognition, we do it because we live in a country that needs a lot of improvements, but when this starts to disturb our work or family compromises we have to stop.
Then I reminded that while working on KieML I found a reference to this project Apache Tika when checking OpenNLP sources and I was also looking for other project to integrate with KieML.

Visit Apache Tika website.

I was afraid about using Apache Tika because it has a lot of dependencies.
org.apache.tika:tika-parsers dependencies 

BUT this ETL part of the project was not for runtime and Apache Tika has a good reason to have so many dependencies: The Apache Tika™ toolkit detects and extracts metadata and text from over a thousand different file types (such as PPT, XLS, and PDF). 
It turns out that then I decided to use and you can see the code I used here:

All the code I needed to use to parse any file to text. You can see it in my github.

Yes, this is all. These lines of code are parsing the XLS or PDF to a String that I can easily transform to JSON. The JSON is then used on a webpage.

The information spread across files is now better organized in a web page

My conclusion here is simple: Apache Tika is a great project and if you are dealing with content from different sources you should at least check it!