This website uses cookies for visitor traffic analysis. By using the website, you agree with storing the cookies on your computer.More information

Category: Development

JVx.vert.x update to vert.x 3.0

Our JVx connection implementation for vert.x is up-to-date. It's now based on vert.x 3.0. We support http and socket connections - no API changes.

Updating to vert.x 3.0 from 2.2 was not funny because package structure was changed and some APIs as well. Whatever, it's working.

If you're interested in our vert.x implementation, check the github repository because we don't offer binaries.

Multi-IDE Feature for next VisionX release

Our current VisionX releases have built-insupport for Eclipse, because every new application is also a complete Eclipse project. Simply import an application in your Eclipse IDE and use all features of your IDE to develop/modify the application.

We didn't support other IDEs like NetBeans or IntelliJ IDEA because Eclipse was our preferred IDE and it's still the most used IDE. But nowadays it makes sense to support the big 3. So, why not :)

Our next VisionX release will come with support for NetBeans and IntelliJ IDEA. Simply open the application and run it. No more manual project creation!

We made a short video which demonstrates our upcoming IDE support. First, an application was created in 1 minute and this application was used with NetBeans, IntelliJ and Eclipse - Open.Run.Done.

Here's the preview video:

Multi-IDE support for VisionX


Above video was made with current development version of VisionX and the next release, with version number 2.2, will be available in this summer.

JVx' JavaFX UI 1.0

We're happy to announce that our JavaFX UI 1.0 was released.

The release contains all planned features and some more. We have the complete MDI implementation, Zoom support for windows and the scene, a custom scene style, custom comboboxes and much more.

MDI control

MDI control

Combobox

Combobox

Styled Scene

Styled Scene

Table format (cells)

Table format (cells)

Zoom

Zoom

Master/Detail with Tables and Tree

Master/Detail with Tables and Tree

All custom controls are available as separate library, JFXtensions. This library will work without JVx because it has no dependency to JVx. Simply use our MDI implementation or zoom feature for your own JavaFX application without using JVx.

Jar files are available at SourceForge or Maven central.

Our next steps?

We'll integrate the UI in our product VisionX to allow Live Preview with JavaFX. The first update release with version number 1.1. will contain smaller bugfixes and improvements based on user feedback.

So, send us your Feedback if you use our library.

AngularJS with JVx in action

Our JVx library has REST support since 2011. It's not only support for using REST libraries, it's a generic solution for action calls and storage access (e.g. database records). This means that your whole business logic is usable via REST with same security restrictions as usual.

In 2011, REST wasn't as popular as today and not supported from soo many different frameworks than today. But now, in 2015, SOAP is legacy and REST is the thing to use. I'm sure you have heard about this modern JavaScript frameworks like AngularJS.

Not sure if it's so successful because it's from Google, but it's often used and developers love working with AngularJS. So we started a simple research project to connect an AngularJS app to our JVx backend application.

AngularJS and JVx is a perfect match because Angular was designed for JS frontends and JVx provides your business logic. Sure, JVx is a full-stack framework and you could create the whole web application, based on vaadinUI, but it's also open for all other UIs.

The most important thing is that everything works out-of-the-box. No additional coding for REST services or authentication, no special knowledge needed. Here's an example service for accessing a customer table (full CRUD support):

public class Customers extends Session
{
        public DBStorage getCustomer() throws Exception
        {
                DBStorage dbsCustomer = (DBStorage)get("customer");
                if (dbsCustomer == null)
                {
                        dbsCustomer = new DBStorage();
                        dbsCustomer.setWritebackTable("customer");
                        dbsCustomer.setDBAccess(getDBAccess());
                        dbsCustomer.open();

                        put("customer", dbsCustomer);
                }
                return dbsCustomer;
        }
}

The class was copied from our DemoERP application (Login as: manager with password: manager). The source code of the whole application is available here.

Yes, there are no more methods like save, update, delete, query, ... The DBStorage encapsulates all calls for you and our generic REST service handles the communication with your business logic.

We have a simple Angular app for you (click on the pencil to edit the record):

This solution is based on AngularJS 1.4.0, Bootstrap 3.3.4 on client-side and JVx with RESTlet on server-side. Here's the JS file:

(function()
{
    var app = angular.module('contactApp', ['ngResource', 'ngRoute']);

    app.config(function($routeProvider)
    {
      $routeProvider.when('/',
      {
        controller:'ListContactsController as contactList',
        templateUrl:'list.html',
        resolve: {contacts: function (Contacts)
                            {
                              return Contacts.fetch();
                            }}
      })
      .when('/edit/:contactId',
      {
        controller:'EditContactController as editContact',
        templateUrl:'edit.html'        
      })
      .otherwise({
      redirectTo:'/'
      });
    });
   
    app.factory('ContactsFactory', ['$resource', function($resource)
    {
       var auth = 'Basic ' + btoa("manager:manager");
       
       return $resource('/demoerp/services/rest/DemoERP/Customers/data/customer/:contactId',
                        null,
                        {'get':    {method:'GET', headers: {'Authorization':auth}},
                         'save':   {method:'POST', headers: {'Authorization':auth}},
                         'update': {method:'PUT', headers: {'Authorization':auth}},
                         'query':  {method:'GET', isArray:true,
                                    headers: {'Authorization':auth}},
                         'delete': {method:'DELETE', headers: {'Authorization':auth}}});
    }]);  

    app.service('Contacts', function($q, $http, ContactsFactory)
    {
      var self = this;
     
      this.fetch = function()
      {
        var deferred = $q.defer();

        return ContactsFactory.query(function(data, status, headers, config)
        {
            self.contacts = data;
           
            deferred.resolve(data);
        },
        function(data, status, headers, config)
        {
            console.log("Error while received data.");
            deferred.reject();
        });
       
        return deferred.promise;
      };
    });

    app.controller('ListContactsController', function(contacts)
    {
        var contactList = this;
        contactList.contacts = contacts;
    });
   
    app.controller('EditContactController', function($location, $routeParams,
                                                     Contacts, ContactsFactory)
    {
        var editContact = this;

        this.fillData = function()
        {
            var idx = Contacts.contacts.reduce(function(cur, val, index)
            {
               if (val.ID == $routeParams.contactId && cur == -1 )
               {
                  return index;
               }
               
               return cur;
            }, -1);
           
            editContact.contact = Contacts.contacts[idx];
           
            editContact.save = function()
            {
                ContactsFactory.update({contactId : $routeParams.contactId},
                                       editContact.contact, function()
                {
                    $location.path('/');
                });
            }
        };
       
        if (typeof Contacts.contacts == 'undefined')
        {
            Contacts.fetch().$promise.then(this.fillData);
        }
        else
        {
            this.fillData();
        }
    });    
})();

It's a useful script because it combines REST with Basic authentication for querying and updating remote database records. Sure, it's not a fat application but this wasn't our intention :)

We have a web application archive for you, if you're interested. Simply use this war together with our DemoERP application and install both applications on e.g. Tomcat application server.

JVx with official connection pooling support

The last black stain was removed. JVx didn't fully support connection pools. It was because of our internal statement cache mechanism and load-on-demand.
We had inofficial support for connection pooling but it wasn't a solution without problems (we weren't proud of it).

With next JVx release or next nightly build, you will be able to use connection pools with same caching mechanism and with full backwards compatibility. We still support load-on-demand for storage records and binary data e.g. BLOBs.

We've some documentation for you:

Connection pooling

and for another new JVx (server-side) feature:

Server-side Call events

Thanks for your patience ;-)

Java Framework comparison and JVx

In the last month we‘ve started a big research project. It is a comparison of Java frameworks for backend and frontend development. We knew that there are many different frameworks for the same job, but which one is the best? Is there one framework that would outpace all others? What are the pros and cons of each framework and how fast could we develop with them?

The idea was trivial: Implementing the same application or screen with different technologies with developers without prior knowledge of the specific technology, always from scratch. Afterwards we could compare the development time, functionality and complexity.

We tried to find out which framework saves most time during development because time is money, e.g. development with framework A needs 6 months and same solution needs 3 months with framework B. Which one is better?

Better doesn't mean that framework B is technological better than A and it doesn't tell us anything about the framework quality. As well, faster is not always better because code quality is very important. We tried to create comparable results and choosen frameworks fulfilled high quality standards. We also knew that every developer is different and development speed matters.

To keep results fair, we tried to find some fresh developers (students) with same experience and without prior knowledge in our framework candidates.

The results were really cool and it was great to get feedback from different developers without marketing slides and no buzzwords. Just reality!

One statistic has extremely amazed us:

Required time (2 passes)

Required time (2 passes)

We tried to use "top-ten frameworks" and our own selection.

Custom comboboxes with JavaFX

We got great feedback about our first beta release of our JavaFX UI. Many of our ideas were right but our comboxes weren't good enough. We had missing features and some technical problems. One missing feature was: Live search in comboboxes with list of values. Our old implementation of comboboxes was like this:

Combo Box

Combo Box

Our implementation didn't support live filtering, e.g. if you typed a key, the list wasn't shortened...

One problem with this feature was JavaFX' focus handling and popups. It was tricky to keep the focus in the right editor and to keep the popup open or to re-open the popup after every keypress. We had a solution but it was too dirty. So we tried to find a better solution. We moved the the editor in the popup, to avoid focus problems. We had crazy effects with two blinking cursors in two different text fields, very strange.

Our current solution is this:

Filterable combobox

Filterable combobox

The design is not perfect but we're working on it. The good thing is that we have no problems with focus and filtering is already working. Here's a screenshot of our date editor:

Date editor in combobox

Date editor in combobox

Our date editor needs a small redesign but it's working. The optimization was planned for release 1.1

If you're interested in our current state, check the source code. We're looking forward to your feedback!

Our code is open source and we still have a separete lib (.ext) for all custom FX controls. The UI implementation for JVx is based on this library. So we have JVx independent JavaFX extensions and our JVx UI implementation.

JVx' vaadinUI and CORS

CORS

All details about Cross-origin resource sharing.

Use-case

Embedd a vaadin application in your CMS (e.g. Joomla, Typo3). The CMS runs in an hosted environment without Java application server (standard and cheap web hosting).

Howto

There's an excellent blog post from vaadin. It's not rocket science to implement this, but you have to do it. We think this things could be done automatically and so we've added the support to our UI implementation for JVx.

It's really simple to use:

Add following parameter to your web.xml:

<init-param>
  <param-name>cors.origin</param-name>
  <param-value>http://www.hosteddomain.com</param-value>
</init-param>
   
<init-param>
  <param-name>pushmode</param-name>
  <param-value>automatic</param-value>
</init-param>
   
<async-supported>true</async-supported>

(be sure that async-support was enabled for all vaadin servlets/filters)

The cors.origin parameter can be a comma separated list.

And here's an example html file:

<!DOCTYPE html>

<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=11;chrome=1" />
    <link rel="shortcut icon" type="image/vnd.microsoft.icon"
          href="./VAADIN/themes/jvx/favicon.ico" />
    <link rel="icon" type="image/vnd.microsoft.icon"
          href="./VAADIN/themes/jvx/favicon.ico" />

    <title>Embedded Vaadin application</title>

    <script type="text/javascript"
             src="./VAADIN/widgetsets/com.sibvisions.rad.ui.vaadin.ext.ui.Widgetset/
                  com.sibvisions.rad.ui.vaadin.ext.ui.Widgetset.nocache.js?05202015200542"></script>

  </head>
 
  <body scroll="auto">
 
    <div id="content">
      <script type="text/javascript" src="./VAADIN/vaadinPush.js?v=7.4.5"></script>
      <script type="text/javascript" src="./VAADIN/vaadinBootstrap.js?v=7.4.5"></script>

      <div id="MyEmbeddedUI" class="v-app">
        <div class="v-app-loading"></div>
        <noscript>You have to enable javascript in your browser to use an application
                  built with Vaadin.</noscript>
      </div>
      <script type="text/javascript">

      if (!window.vaadin)
      {
        alert("Failed to load the bootstrap javascript:
               ./VAADIN/vaadinBootstrap.js?v=7.4.5");
      }
   
      vaadin.initApplication("MyEmbeddedUI",
                             {"browserDetailsUrl": "ui/" + appname + params,
                              "serviceUrl": "ui/",
                              "theme":"jvx",
                              "versionInfo":{"vaadinVersion":"7.4.5",
                                             "atmosphereVersion":"2.2.4.vaadin5"},
                              "widgetset":"com.sibvisions.rad.ui.vaadin.ext.ui.Widgetset",
                              "comErrMsg":{"caption":"Communication problem",
                                           "message":"Take note of any unsaved data,
                                                      and <u>click here</u> or press ESC to
                                                      continue.",
                                           "url":null},
                              "authErrMsg":{"caption":"Authentication problem",
                                            "message":"Take note of any unsaved data,
                                                      and <u>click here</u> or press ESC to
                                                      continue.",
                                            "url":null},
                              "sessExpMsg":{"caption":"Session Expired",
                                            "message":"Take note of any unsaved data,
                                                      and <u>click here</u> or press ESC key
                                                      to continue.",
                                            "url":null},
                              "vaadinDir":"./VAADIN/",
                              "standalone":false,
                              "debug":false,
                              "heartbeatInterval":300,
                              "comErrMsgDetails":true,
                              "authErrMsgDetails":true,
                              "sessExpMsgDetails":true});
      </script>
    </div>
  </body>
</html>

And the rest of our web.xml:

<servlet>
  <servlet-name>EmbeddedUI</servlet-name>
  <servlet-class>com.sibvisions.rad.ui.vaadin.server.VaadinServlet</servlet-class>
  <init-param>
    <param-name>UI</param-name>
    <param-value>com.sibvisions.rad.ui.vaadin.impl.VaadinUI</param-value>
  </init-param>
  <init-param>
    <param-name>widgetset</param-name>
    <param-value>com.sibvisions.rad.ui.vaadin.ext.ui.Widgetset</param-value>
  </init-param>
  <init-param>
    <param-name>main</param-name>
    <param-value>com.sibvisions.apps.MyEmbeddedApplication</param-value>
  </init-param>
  <init-param>
    <param-name>Launcher.uifactory</param-name>
    <param-value>com.sibvisions.rad.ui.vaadin.impl.VaadinFactory</param-value>
  </init-param>
  <init-param>
    <param-name>pushmode</param-name>
    <param-value>automatic</param-value>
  </init-param>

  <async-supported>true</async-supported>  </servlet>
</servlet>

<servlet-mapping>
  <servlet-name>EmbeddedUI</servlet-name>
  <url-pattern>/*</url-pattern>
</servlet-mapping>

The application was deployed in ROOT context of Tomcat8.

If you have a different context, simply change the URLs: browserDetailsUrl, serviceUrl and vaadinDir (see html page).

The CORS support is not available in our latest vaadinUI release (1.2), because its a very new feature. Simply use our nightly builds for testing.

Happy embedding.

Demo ERP 1.1, iOS & Android App updates

First, we've released version 1.1 of our Demo ERP application. The full source code is available on SourceForge. It doesn't have more features than 1.0 because it's a simple lib upgrade release with improvements for developers.

The DemoERP.zip now contains the whole project structure and not only the source files. Simply unzip the archive, import the project in your Eclipse IDE and start the DemoERP.launch file (sure, DB must be configured manually). The archive contains small README files with additional information.

We fixed code signing problems and you shouldn't have any problems with DemoERP.war. So, simply deploy the war and open http://localhost/DemoERP/web/ui in your browser (see README).

The release contains our latest vaadinUI based on 7.4.5 and our latest JVx.mobile lib. The mobile lib was needed for our updated mobile apps for iOS and Android.

Yepp, we've new apps in the stores (still native but not based on JavaFX). The apps have a buch of new features like custom view styles (based on style property of JVx), image viewer/editor or the new Form view. But the biggest improvement was offline support. It's now possible to switch to offline mode and back to online mode. Sure, we sync your offline data!

It's an awesome feature because it's a generic solution and you don't have to change anything in your application. It simply works!

Both applications have the same features but system specific.
Here's the iOS link.
The Android app via Google Play.

Both apps work great with latest VisionX releases and simply use it to test your VisionX application - LIVE - without redeployments - on your mobile devices!

Zoom support for applications

Some weeks ago, JavaFX links of the week contained a very interesting link: It was about ZoomFX 1.0.1.

It's a zoomable pane for your JavaFX application.
There's another small project, called MagniFiX. It's a "simple" magnifier but different than ZoomFX.

Why was this so interesting for us?

In the past we had a lot of requests from customers for automatic application scaling for simple touch devices (terminals). Usually we solved the problem with extra source code and specific fonts/control settings - horrible.

We had other requests about image zoom in/out features and charts, ...

So we thought that ZoomFX could be a very useful extension for our JavaFX UI. We tried the demo and configured a simple test application. But first: Maven. Not new: We aren't big fans.
Sure, it wasn't hard to start a test application but we were suprised about the dependencies:

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-math3</artifactId>
</dependency>

<dependency>
    <groupId>com.github.dejv78.commons.jfx</groupId>
    <artifactId>jfx-binding</artifactId>
</dependency>

<dependency>
    <groupId>com.github.dejv78.commons.jfx</groupId>
    <artifactId>jfx-geometry</artifactId>
</dependency>

<dependency>
    <groupId>com.github.dejv78.commons.jfx</groupId>
    <artifactId>jfx-input</artifactId>
</dependency>

The overlays were saved as FXML and we thought that it's not a good idea for a library like ours. Anyway, we tried the integration in our lib and stopped suddenly because ZoomFX didn't work with our dynamic layouts. It simply didn't work out-of-the-box and it had too many dependencies for such a "simple" feature.

We had no luck... but we love researching new things. So we started with our own zoom implementation without any dependencies and also integrated in our UI. We made a short screencast of the result.

Application coder

Every application and internal frame has this zoom feature because it was integrated in the UI implementation. We need to do some fine tuning, but it works great!