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

EPlug - The Big Guided Tour

Since last year we are offering an Eclipse Plugin that integrates  the JVx workflow into Eclipse. Now that EPlug 1.2 has been released, we believe it's long overdue to give you a guided tour of the experience that EPlug is offering.

Trial

We offer a free trial period so that you can test EPlug without any problems. The first time you start Eclipse with EPlug you will be asked if you'd like to only test EPlug, or if you'd like to select an already purchased Pro license.

Showing the EPlug license welcome screen.

When clicking the Trial button, a new trial license will be issued and you'll be able to evaluate EPlug with all features for 30 days.

Showing the trial window.

'First Run' Wizard

One of the biggest usability improvements compared to previous versions is discoverability of how to use and activate EPlug. With the new version we have added a "First Run Wizard" which allows to directly activate EPlug on selected projects.

First Run Wizard

Usage

EPlug integrates seamlessly into Eclipse, but to use most of its features it has to be activated on each project you want to use it with. This can be done in the previously shown First Run Wizard, or by right-clicking a project and selecting "Activate EPlug" under "Configure".

Showing how to activate EPlug.

From there on you will be able to use code completion, compile time checks and all the other features on this project.

Better and extended commands

A handful of commands are added by EPlug, which make it faster to navigate in JVx projects.

Go to complement class

It's often the case that you want to go from the server to the client class, or from the client to the server class. Most of the time in Eclipse this involves expanding trees and looking for the correct class in the Package Explorer. That is why we've implement the command "Go to complement class", which enables you to quickly jump from the server to client, or the other way round.

The context menu of Eclipse showing the "Go to complement class".

As you can see the command is available from the context menu, but you can also bind it to a key in the "Keys" preferences.

Showing the motion of the command.

Open Declaration

The "Open Declaration" command, sometimes known by its key binding "F3", allows you to jump to the declaration of whatever is currently under the cursor. We've extended this command with the possibility to jump to the declaration of event handlers (actions), server methods and storage's. If the item underneath the cursor is not handled by our extension, the default "Open Declaration" command will be invoked.

The context menu of Eclipse showing the "Open Declaration (EPlug)" command.

The declaration:

Showing the target of the command.

Because we've extended the "Open Declaration" command, you can bind the "Open Declaration (EPlug)" command also to "F3" and enjoy faster navigating in your JVx files without any downsides.

DataBooks

The biggest and most important feature of EPlug is its support for data books. EPlug offers code completion, compile time checks and more for column names on remote and local data books.

Code completion

Everytime you want to get or set a value, or wire up an editor you will receive code completion suggestions with all column names that are in the databook, it doesn't matter if those are remote or added locally.

Showing the code completion of columns.

Compile time checks

Of course we also added compile time checks, which means that you can never mistype a column name ever again.

Showing the compile time checks of column names.

With the newest version, these compile time checks are even active while you type!

Text hovers

When hovering above a column name, a simple text hover will inform you about the type of the column.

Showing the text hovers of columns.

Storage support

RemoteDataBooks require to have the correct name set so that the server side storage is found, of course we do also offer code completion, compile time checks, text hovers and hyperlinks for this.

Showing the code completion for storages.

Showing the compile time checks of storages.

The DataBook View

And last but for sure not least, with the newest version a feature has been added which I've been looking forward to for quite some time: The DataBook View. A view similar to the Outline view, which displays all databooks in the current file and all of its columns.

Showing the DataBookView.

Actions/Events and server calls

Support for actions, events and server calls is the second big EPlug feature. For events and actions we support a very Lambda-like system that uses reflection and strings. Obviously the compiler was never able to understand this system and provide feedback or support for it, but with EPlug this has changed.

Code Completion

Whenever you want to wire up an event, you'll now receive code completion for all fitting methods in the used class.

Action methods:

Showing the code completion for events.

Remote calls:

Showing the code completion for server calls.

As you can see in upper image, we also provide a fast and convenient way to create methods if necessary.

Compile time checks

During compilation the actions, events and server calls are checked for their correctness, and if there is a problem it'll be reported to you.

Showing the compile time checks of actions.

You can also see the quick fixes for this problem, which do not only offer to create the missing method, but also suggesting methods with similar names in case a typo happened.

Text hovers, hyperlinks and refactoring support

Additionally EPlug provides text hover and hyperlink support, that means that you can now jump to the methods by using your mouse (Ctrl+Left Click) or the "Open Declaration (EPlug)" command. Refactoring support has also been added, which means that you can now rename action/event handlers without having to manually search for all uses and change those.

Resources

Dealing with resources can often be a pain in the neck, especially if you constantly have to look up the path and check if you're now using the correct image. Because we also felt these pains, we've added functionality to EPlug to make sure that working with resources becomes easy and painless.

Support for UIImage

Whenever you use UIImage methods, you can now enjoy code completion, previews of the images and compile time checks.

Showing the code completion for UIImage.

Preview:

Showing the preview of images in UIImage.

Compile checks:

Compile time checks of resources.

Generic resource completion

For all other resources, we do only offer a "generic" code completion system and no preview. Still, this is a huge help.

Showing the code completion for other resources.

Comments

One of the more simple and not so obvious features of EPlug is that it allows to have code completion of the current class in comments, and also provides the JVx category separators.

Showing the code completion for comments.

Separator:

Showing the code completion for comments.

Action/call completion in comments:

Showing the code completion for comments.

VisionX support

Now we've arrive at the big final, support for VisionX. For all of you who do not know VisionX, it is our product for rapidly building applications from scratch or migrating already existing systems. It allows to build GUIs and the respective database backend within a matter of minutes. Even though VisionX allows you to build whole applications, from time to time you'll want to do something by hand and this is the great thing about VisionX, all projects and applications are automatically and by design already Eclipse projects. So all you need to do is import the project into Eclipse and start working on it. To improve this workflow further EPlug does offer various features.

Selection synchronization

The selection in Eclipse and VisionX can be automatically synchronized, so that whatever you're working on in the one application is also visible and selected in the other

Showing the selection between VisionX and Eclipse.

Automatic applying of changes

VisionX will also automatically refresh its current view if you change a sourcefile in Eclipse, allowing to rapidly and verify changes in a workscreen without the need to manually reload the workscreen.

How and where to get it?

EPlug comes in two flavors, EPlug for JVx and EPlug for VisionX, both are available from the Eclipse Marketplace and can be installed and used freely for 30 days. Afterwards a license is necessary to keep using all features.

JavaFXPorts with iOS

I wrote a blog post about JavaFXPorts and Android some weeks ago.

At last Eclipse DemoCamp in Vienna, Tom Schindl asked me about the startup performance on iOS, because his experience with startup performance was horrible with early RoboVM versions. I had no answer because we didn't test our app with iOS and... the question didn't get ouf of my head. Sure, I knew that RoboVM was tuned in last two versions but didn't test it myself.

So, yesterday I had the time to test it out and... Startup and overall performance was same as on Android device!
The iOS device was an iPad Air2 and Android device was Nexus9. The performance may be worse on older devices.
Performance? Application start was finished after touch event (< 1 sec).

My test wasn't as simple as expected because RoboVM has some specifics and iOS needs code signing in order to run an app on real hardware. Also my JVx library (jvx.jar) wasn't usable because it contained SwingUI and one class of it was accessing a member of a parent class:

public class JVxCalendarPane extends JPanel
{
   
    ...
   
    public void addActionListener(ActionListener pActionListener)
    {
        listenerList.add(ActionListener.class, pActionListener);
    }
}

The listenerList is a member of JComponent:

protected EventListenerList listenerList = new EventListenerList();

But the member is not available in RoboVM' phantom class. The solution was easy: Removing SwingUI from jar.
A nice feature for RoboVM would be an ignore list of classes/packages.

Here's a picture of our DemoERP application on iOS:

DemoERP on iOS tablet

DemoERP on iOS tablet

It's working :) but still, a Desktop application 1:1 on a tablet isn't the best idea, e.g. the device type (iPad) or WLAN icon is over the application menu. The iOS port has some problems with TextFields, but we'll report an issue.

Thanks to JavaFXports the creation and deployment of our JavaFX app was super easy!

OpenShift Deployment

OpenShift is a PaaS product from Red Hat.
Read further details at Wikipedia or the product site.

It's of interest to us because it's easy to use, supports deployment of pre-created war files and it offers an application server (e.g. Tomcat, JBoss) and a database (MySQL, PostgreSQL) for your applications. OpenShift also has Vert.x as runtime platform if you won't use an application server. The configuration is super easy and your server is ready in around 5 minutes.

The access to your server is protected and you should use a specific client tool from RedHat for advanced configuration or an SSH client like putty.

The PaaS service is so nice because it's the perfect deployment platform for JVx applications. There's a free service for simple tests and maybe smaller applications because there are some limits for memory usage, CPU, and number of applications.

We made some tests with OpenShift and the result was as expected: Our applications did work without problems. Sure, the whole deployment procedure could be more end-user friendly but it wasn't designed for end-users without technical know-how, I guess. It's good enough for software developers or admins.

Our test

We created a new JVx application with VisionX (because it creates the database, has a GUI builder and creates the war file for us) and the application should run with VaadinUI on OpenShift. We didn't have any experience with OpenShift, but with other PaaS products, e.g. Heroku, Cloudbees, Jelastic, AWS.

First steps:

  1. Registering an account (what else :) )
  2. Creating a first application
  3. Cartridge: Tomcat 7 (JBoss EWS 2.0)
  4. Setting application name and domain
  5. Adding MySQL 5.5 cartridge

Above steps were enough to run our OpenShift service(s).

Next was accessing the server via SSH client because we didn't install the RedHat client tool (We won't use client tools for cloud services - why the hell). Sure, we had to use another client tool for accessing the server via SSH, but it was working without installation: PuTTY (still strange). A nice web UI would be great... just my thoughts. We found a Java client but didn't test it.

So, what we did:

  1. Creating private/public RSA keys with PuTTYgen
  2. Configuring OpenShift (used the key from PuTTYgen TextArea because OpenShift didn't like other formats)
  3. Testing connection

    Username was displayed in Application settings under SSH Code, e.g. ssh://<username>@app-domain.rhcloud.com/....
    Used the private key file for putty as key (Key authentication, without password)

Next task was, configuring the access to the database because SSH access was already working. It wasn't possible to access the database without tunnel - means, no direct (Internet) access from your client. This wasn't a real problem and PuTTY had support for port tunneling. Simply detected the IP address of the MySQL server. The hostname was set as environment variable and the command export displayed all variables. The variable OPENSHIFT_MYSQL_DB_HOST had all information and our tunnel was working. There's also a property for the MySQL Port but 3306 is default.

What was next?

Deployment.

This wasn't trivial because the platform expected source code and a maven project for automatic deployment. Wrong for us. But there's an official documentation for manual war deployment.

Short summary of steps

  1. GIT clone
  2. Delete src folder and pom.xml
  3. GIT commit & push
  4. Copy WAR file into webapps folder
  5. GIT commit & push

You don't need git on your client, it's available in your terminal. But... as a developer, git is one of those standard tools...
It's also possible to upload the WAR file via SCP or SFTP...

Done...

Not really because our application was deployed without problems but it didn't work because the JDBC URL was wrong. We set the MySQL servername to localhost because of the tunnel!

Here's the original config.xml:

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

<application>
  <securitymanager>
    <class>com.sibvisions.rad.server.security.DBSecurityManager</class>
    <accesscontroller>com.sibvisions.apps.server.object.DBWorkScreenAccess</accesscontroller>
    <passwordalgorithm>SHA</passwordalgorithm>
  </securitymanager>
  <connection>
    <!-- GLOBAL | DATASOURCE | OFF -->
    <property name="client.metadata_cacherole">OFF</property>
  </connection>
  <lifecycle>
    <application>com.sibvisions.apps.openshifterp.Application</application>
    <mastersession>com.sibvisions.apps.openshifterp.Session</mastersession>
  </lifecycle>
  <datasource>
    <db name="default">
      <url>jdbc:mysql://localhost:3306/erp</url>
      <username>username</username>
      <password>password</password>
    </db>
  </datasource>
</application>

JVx has a nice feature which allows environment dependent settings and VisionX sets the environment automatically to prod. So, we simply changed the datasource to:

<datasource>
    <db name="default">
      <url>jdbc:mysql://localhost:3306/erp</url>
      <url_prod>jdbc:mysql://hostname_from_env_variable:3306/erp</url_prod>
      <username>username</username>
      <password>password</password>
    </db>
  </datasource>

VisionX sets the environment to prod, if it creates a WAR file:

<securitymanager>
    <class>com.sibvisions.rad.server.security.DBSecurityManager</class>
    <accesscontroller>com.sibvisions.apps.server.object.DBWorkScreenAccess</accesscontroller>
    <passwordalgorithm>SHA</passwordalgorithm>
    <environment>prod</environment>
  </securitymanager>

Sure, the solution isn't perfect because the MySQL hostname should be read from the environment variable.
Would be better:

<url_prod>jdbc:mysql://${env:OPENSHIFT_MYSQL_DB_HOST}:${env:OPENSHIFT_MYSQL_DB_PORT}/erp</url_prod>

But JVx doesn't support this syntax (right now) -> Feature Request.

Done. Really done.

The application works fine (Login as admin with password admin).

Here's a screenshot, for the case that our OpenShift service isn't running:

OpenShift ERP with JVx and VaadinUI

OpenShift ERP with JVx and VaadinUI

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.