quinta-feira, 1 de novembro de 2018

Adding dynamic properties to a Javascript object in a GWT + JSInterop context

GWT is a framework that allows you to program the user interface of your application in Java and later it is compiled to Javascript, which will work across all browsers. The main advantage is that you don't have to care about minification of Javascript and compatibility across browsers, easy communication with server side and it is Java, you can use Java on server and client side. With Errai you have CDI (and more) on the client side, which means that you can make your application flexible and create pluggable components.
GWT in its later versions introduced JSInterop, a great way to call Javascript using Java. During the compilation the Java bean will be compiled to an equivalent Javascript code. This is good for Javascript objects with static properties, but knowing Javascript you will always find cases where the attribute name is dynamic, where the attribute is created "on the fly", for example:

var myObject = {
    someAttributeIJustCreated : "the value"

In Javascript myObject is a valid type, but this is not how things work with Java. During Javascript development it is handy to use such types and in some Javascript APIs you can't run away from it, for example, in C3.js to map a data X value you must create an attribute with the name of the column matching the column name where the X values will be found. To better understand this see the simple_multiple_xy.js example:


var chart = c3.generate({
    data: {
        xs: {
            data1: 'x1',
            data2: 'x2',
        columns: [
            ['x1', 10, 30, 45, 50, 70, 100],
            ['x2', 30, 50, 75, 100, 120],
            ['data1', 30, 200, 100, 400, 150, 250],
            ['data2', 20, 180, 240, 100, 190]

Notice that to tell that data1 x will x1 we will need to have an attribute of type data1. If you know the API you will see that data1 could be a String, but that I don't know how to map.
How do we map such cases using JSInteorp? After looking for it quite a while I found this github discussion and then the solution was simple:

* Make the attribute of type elemental2.core.JsObject
* Use the following code to create dynamic attributes:

JsObject jsObject = JsObject.create(null);
       .set("someCustomProperty", "someCustomValue");

And that's it! You can have properties of type JsObject in any object anotated with JsType, for example, if I want to create xs attributewith dynamic attributes (see the c3 object above), I can declare a property as follows:

    public native void setXs(JsObject xs);

See you in next post.

segunda-feira, 15 de outubro de 2018

Debugging error "Could not import XML from stream: invalid LOC header (bad signature)" when building a Thorntail application

Tl;DR: Check if there's corrupted JARs in your maven repository

When building a Thorntail 2.2.0.Final application I faced the error Could not import XML from stream: invalid LOC header (bad signature) when trying to build the JAR using mvn clean install. I could not find what is wrong, I just downloaded the application using Thorntail generator but I was not able to run it, so frustrating. When I used the -X flag I could see the error stack trace. The part that was causing the error was:

Caused by: java.util.zip.ZipException: invalid LOC header (bad signature)
    at java.util.zip.ZipFile.read (Native Method)
    at java.util.zip.ZipFile.access$1400 (ZipFile.java:60)
    at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse (DocumentBuilderImpl.java:339)
    at javax.xml.parsers.DocumentBuilder.parse (DocumentBuilder.java:121)
    at org.jboss.shrinkwrap.descriptor.spi.node.dom.XmlDomNodeImporterImpl.importAsNode (XmlDomNodeImporterImpl.java:65)
    at org.wildfly.swarm.tools.ModuleAnalyzer. (ModuleAnalyzer.java:53)
    at org.wildfly.swarm.tools.ResolvedDependencies.findModuleXmls (ResolvedDependencies.java:80)

If you check the full stack trace you can see that the problem is coming from some corrupted zip file in my local maven repository. The simply solution would be clean my local maven, but I didn't want to do that, so I had to debug ResolvedDependencies  class. Code is open, I cloned the thorntail project from github, imported the project tools to my Eclipse, checked the 2.2.0.Final TAG, configured remote Java application debug adding the tools projects in source tab:

Then I added a breakpoint to the point where the exception was thrown: 

Finally I run the maven using mvnDebug When you do this maven hangs waiting for a remote debugger to connect to it, then I had to go back to Eclipse and run my Remote Java Application goal:

When it stopped at my break point I was able to continue the debug execution in debug mode and back to ResolvedDependencies I could see what JAR was corrupted. After the debug session session I simply had to delete the JAR and run mvn clean install again and everything worked because maven re-downloaded the JAR, this time a not corrupted one :-)

sexta-feira, 1 de junho de 2018

Very simple chat using JGroups and JavaFX

I just wanted to share this small application using JGroups and JavaFX. JGroups is "a toolkit for reliable messaging" and one of the oldest and stable Java libraries.
The chat code I used was the same one from JGroups sample code page, we need less than 5 codes to implement all the chat functionality!

sexta-feira, 25 de maio de 2018

The Image Classifier Microservice is public on Docker repository

Using fabric8 docker plugin and the project from A Java microservice for image classification using Thorntail and DeepLearning4J post I was able to build a docker image and I pushed it to my Docker repository!

In this post I am sharing the steps I followed to build the docker image and publish it. Next post I hope to show you how to run on Openshift with some real world application.

Step 1: Build an image from the Thorntail project

This is simple, you will need just a configuration in the maven descriptor, see the changes in the project pom.xml.

Notice that I had to made a manual copy of a JAR file as described in Thorntail's issue #951, however, I am probably missing something, that may not be a bug,. Let's wait to see what Thorntail team will provide as a feedback for that issue. I wasn't a bug, Bob just commented on the issue, the solution is not use the thin mode.

For having help I pinged Thorntail users on #thorntail IRC channel in freenode and Ken Finingan helped me, also, Bob helped me to get started with Thorntail when I wrote "". Both are Thorntail core contributor and they were so kind and patient to me (also others Thorntail users) that I had to mention them here!

Step 2: Test the image

Testing the image is simple. Run it using docker:

docker run -di -p 8080:8080 fxapps-image-classifier/app

It will start the app and bind it to your local port 8080. So when the image is build you can test it using curl:

curl  http://localhost:8080

If it is working if you see a big JSON as response! 

Step 3: Push the image

I followed the instructions from Docker documentation and the image is public now, meaning that you can pull this image and run locally.

If you have docker and want to give it a try first you must pull the image:

docker pull jesuino/image-classifier

Then run it:

docker run -di -p 8080:8080 docker.io/jesuino/image-classifier

Follow the logs until you see that thorntail is started:

INFO  : Sat May 26 03:04:32 UTC 2018 [io.thorntail.kernel] THORN-000999: Thorntail started in 71.896s

Notice that it took more than 1 minute to run because I didn't use a custom model, instead, I let it download from DeepLearning4J Zoo.

Once Thorntail is started you test the service: curl  http://localhost:8080


Yes, Thorntail doesn't even have a final release, we have been using snapshot releases and it is cloud ready. Next steps is to improve the microservice by adding health check and then deploy it to Openshift with a real world application!