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

Posts tagged: JVx

JavaFX Table and Tree lazy loading

JavaFX doesn't define a specific model for table or tree. The implementations are based on ObservableList which is not more than an extension of standard List interface with some additional listeners and sorting, filtering. The general design doesn't take care of one important feature: Lazy loading of records.

This is an important feature if you're working with databases or large datasets. If you have millions of records, it's not a good idea to show all records in your GUI. You shouldn't load more than needed and of course, not more than the user is able to handle.

We have a model in our JVx framework which supports lazy loading of records (not only database records). To use our model with JavaFX, we had to do some Trial and Error because an ObservableList is too lightweight. Sure it wasn't a problem to simulate more entries than the list really had. This was needed to load records on demand. If a "virtual" element was requested it was simply loaded from the datasource. Sounds simple enough. To be honest - it was that simple!

A bigger problem was the scrollbar handling of the controls because it didn't set the scrollhandle position correctly after loading "virtual" records. We didn't find a perfect solution for this problem but our current solution works and is user-friendly enough. We've used our JVx model implementation for TableView and TreeView.
Means: One model for all UI controls.

A simple screencast of our test application is available on YouTube. The video shows a simple TableView which loads records from a remote server via http. The remote server reads data from a HSQLDB. The table contains 317027 records with filenames and additional filesystem information. The remote server returns exactly 100 records, per request, for our test application.

LazyLoading JavaFX TableView


We have the same lazy loading mechanism for TreeView.

Our implementation was done for JVx' model (IDataBook), but the mechanism should work with any other model definition. The complete source code is available in our dev repository. Simply start with ObservableDataBookList.

JavaFX Tree with self-joined table

Trees are always tricky, because it's not easy to fill a tree with data. The problem is not the tree itself, but the preparation of data for the three. It's easy if your data is structured or if you have only few records to prepare. If you have differnet datasources, it could be very tricky to build a tree.

The official tree documentation from Oracle has some examples.

It's boring to create trees because it needs a lot of boilerplate code - per tree. You need more boilerplate code if your trees should be editable.

We solved the "boilerplate code problem" with JVx and the active model implementation. I'll show you a simple example with a self-joined database table. The database table contains all filesystem folders of our Linux test VM.

The table was created with following statement:

CREATE TABLE FOLDERS
(
  ID        INTEGER IDENTITY,
  FOLDER    VARCHAR(256) NOT NULL,
  FOLD_ID   INTEGER,
  constraint FOLD_UK UNIQUE (FOLD_ID, FOLDER),
  constraint FOLD_FOLD_ID_FK FOREIGN KEY (FOLD_ID) REFERENCES FOLDERS (ID) ON DELETE CASCADE
)

Not really tricky. The table contains an unique identifier, the folder name and the identifier of the parent folder. A simple self-joined table.

The UI code for the tree:

IDataBook dataBook = createDataBook();

FXDataBooksTree tree = new FXDataBooksTree();
tree.getDataBooks().addAll(dataBook);

Short and no boilerplate code!
The missing piece is the createDataBook() method, because it defines the access to our database table:

RemoteDataBook rdbData = new RemoteDataBook();
rdbData.setDataSource(getDataSource());
rdbData.setName("folders");
rdbData.setMasterReference(new ReferenceDefinition(new String[] {"FOLD_ID"},
                                                   rdbData,
                                                   new String[] {"ID"}));
rdbData.open();

The code is similar to other examples likeJavaFX, JVx and data binding or Plain JDBC vs. DBStorage.

The tree will look like this one:

Self-joined tree

Self-joined tree

The whole source code is available in our dev branch.

Above test application reads records from a remote database via http, but it could also use a memory databook without database access, like this one:

IDataBook dataBook = new MemDataBook();
dataBook.getRowDefinition().addColumnDefinition(new ColumnDefinition("ID",
                                                new BigDecimalDataType()));
dataBook.getRowDefinition().addColumnDefinition(new ColumnDefinition("PARENT_ID",
                                                new BigDecimalDataType()));
dataBook.getRowDefinition().addColumnDefinition(new ColumnDefinition("NAME",
                                                new StringDataType()));
dataBook.setMasterReference(new ReferenceDefinition(new String[] { "PARENT_ID" },
                                                    dataBook,
                                                    new String[] { "ID" }));
dataBook.setName("MASTER");
dataBook.open();

An example with a MemDataBook is available in our kitchensink application.

JavaFX + Android + Live Preview

We had a lot of fun this week - with JavaFX :)

My last article was about JavaFX on mobile devices with JavaFXPorts. It was awesome that JavaFX worked without bigger problems on mobile devices but the number of needed re-deployments was high. The app build process needs some time (~2-3 mins) and if you do a lot of UI related changes in your application (CSS, layout, ...) you lose development time.

How to save deployment time?

Simply don't deploy!

We have our product VisionX and it has a Live Preview for applications while developing. Our idea was that we could use the existing functionality to show changes on mobile devices immediately. It should work with Android devices because dynamic class loading is possible with custom classloaders.

But as so often, things won't work as expected.

Android has support for URLClassLoader but it doesn't work because the implementation is "legacy" . This means that loading classes with URLClassLoader didn't work. Android has a DexClassLoader!

The DexClassLoader works great if you have the archive on the device. But it has no support for remote class loading. The other thing was that DexClassLoader needs a jar that contains a classes.dex archive. The classes.dex contains all class files (in dex format).

The first problem was: How to create the DEX archive?

Not too hard because Android comes with dx.bat and dx.jar. It's super easy to convert a jar file or a classes folder to a dex archive. After the hardest part was solved, it was simple to implement remote class loading with Android, for our JavaFX application! If you need more information, leave a comment!

Here's the result of our Live Preview experiment as Video:

Window shutter web control

It works great and reduces deployments to a bare minimum: 1

JVx' JavaFX UI with JavaFXPorts

A few hours ago, we published a screenshot from our Demo ERP application running on Nexus 9 (an Android tablet).
It wasn't a fake!

Before we'll show you more screenshots, we want say that we've reached a long awaited goal!

Use JVx and write an application for all polpular platforms and devices.
This is real "write once run anywhere".

Create an application for Windows, Linux, Mac, iOS, or Android, PS4, OUYA or WiiU. Run it as desktop application, as html5 application in web browsers, as native iOS or Android application or as JavaFX application on Android and iOS devices. There's nothing like JVx in the world - not with only one framework with such a small footprint as JVx and certainly not Open Source!

Here are the screenshots:

Maximized frame with charts

Maximized frame with charts

Frame with tree

Frame with tree

Also in portrait mode:

Portrait mode

Portrait mode


And now a very strange one. It's the application with our styled stage. It's crazy because you can drag the window around (makes no sense, but it just works):

Styled stage with tabset desktop

Styled stage

Sure, the application wasn't optimized for mobile devices. It has the same style as the desktop application. The mobile version should have bigger frame buttons and a bigger frame header :) To be honest - MDI on mobile devices? We were positively surprised about the usability. But, whatever. You have the option and decide what's best for your application (but please don't use MDI for smartphones).

Are you interested in some details?

We've used Netbeans IDE because there's a very useful plugin from gluon. We're Eclipse users but it was easier to use a preconfigured environment without doing everything manually. It was simple to configure Netbeans with gluon plugin and there's a video for your first steps. A "bigger" problem was gradle because the project was a gradle project and we've never used gradle. We love using ant.

We had a bad start with Hello World application because it didn't work. There were different problems: Missing ANDROID_HOME or DEX compiler problems. After reading the documentation it was possible to start compilation. The DEX problem was very strange because we had JVM 1.8 u31 and JVM 1.8 u40 configured in Netbeans, but Netbeans didn't use our configured JVM 1.8 u40. We removed the JVM 1.8 u31 from Netbeans and after that we successfully compiled our Hello World application. Very strange!

The next step was using JVx as library dependency for our project, but how did this work with gradle? We had the library in the libs directory of the project, in the file system. We didn't use a maven lib because it was easier to replace the library after recreation. We tried to find a solution in the official gradle documentation and found Chapter 51. C'mon gradle is a build tool and not a programming language! So much documentation means: complexity. Sure, ant wasn't the holy grale but it it's simple to understand and doesn't hide anything.

Our current gradle script:

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'org.javafxports:jfxmobile-plugin:1.0.0-b7'

    }
}

apply plugin: 'org.javafxports.jfxmobile'

repositories {
    jcenter()
}

dependencies {
    compile fileTree(dir: 'libs', include: '*.jar')
    runtime fileTree(dir: 'libs', include: '*.jar')
}

mainClassName = 'com.sibvisions.gluon.JVxGluonApp'
   
jfxmobile {
   
    ios {
        forceLinkClasses = [ 'com.sibvisions.gluon.**.*' ]
    }
   
    android {
      androidSdk = 'C:/tools/android/android-sdk_r04-windows'
      compileSdkVersion = 21  
    }
}

It's short but we ddin't know what happened behind the scenes without additional research. But if it works it's good enough for many developers.

The integration of JVx was simple because JVx was compiled with JVM 1.6. The Dalvik VM or DART do support 1.6 and 1.7 syntax. It was cool to see that JVx and especially the communication worked without problems - Great job from Johan Vos and all people behind JavaFXPorts!

Our next step was the integration of additional dependencies like our JavaFX UI. It was based on JVM 1.8 u40 and heavily used lambdas. But lambda expressions weren't supported from Dalvik or ART. We thought that gluon plugin solves the problem for us, but it didn't. It contains retrolambda but only for project source files and it doesn't touch your dependencies. There was no additional gradle build task for that, so we had to convert the libs manually. Not a problem but you must be aware of it.

After we solved all dependency problems, we had the first version of our desktop ERP running on our android device. But don't think everything was trouble-free. We had problems with method references, Java Preferences because of write problems, new Date API, forEach calls, scene size and much more. We did solve most problems but not all - yet.

Charts with JVx and JavaFX

In my last article about JavaFX, JVx and data binding you saw a first impression of our chart binding. We have additional screenshots for you. The first two images show a Swing application with different charts. The next two images show the same application, with JavaFX. Which UI do you like more?

Bar chart with Swing

Bar chart with Swing

Line chart with Swing

Line chart with Swing

Bar chart with JavaFX

Bar chart with JavaFX

Line chart with JavaFX

Line chart with JavaFX

The JavaFX UI is clean and fresh. It looks modern compared to Swing. A desktop application should look modern and not dusty!

How about the data binding?

Our screen has two charts. Every chart gets its records from a data book (our model class). The labels and values are dynamic and every change in the databook updates the chart. Here's the source code for the chart definition:

//BAR chart
UIChart chartBar.setChartStyle(UIChart.STYLE_BARS);
chartBar.setTitle("Annual Statistics");
chartBar.setXAxisTitle("Year");
chartBar.setYAxisTitle("Grosstotalprice");
chartBar.setDataBook(rdbV_statistic_order_offer_year);
chartBar.setXColumnName("YEAR_");
chartBar.setYColumnNames(new String[] {"OFFER_GROSSTOTALPRICE", "ORDER_GROSSTOTALPRICE"});

//LINE chart
UIChart chartLineArea.setChartStyle(UIChart.STYLE_LINES);
chartLineArea.setTitle("Monthly Statistics");
chartLineArea.setXAxisTitle("Month");
chartLineArea.setYAxisTitle("Grosstotalprice");
chartLineArea.setDataBook(rdbV_statistic_order_offer_month);
chartLineArea.setXColumnName("MONTH");
chartLineArea.setYColumnNames(new String[] { "OFFER_GROSSTOTALPRICE", "ORDER_GROSSTOTALPRICE" });

The complete source code is available on sourceforge. It's from our Demo ERP application.

The databooks are remote databooks because our Demo ERP is a 3-tier application. The databook definition:

//BAR Chart
RemoteDataBook rdbV_statistic_order_offer_year = new RemoteDataBook();
rdbV_statistic_order_offer_year.setName("v_statistic_order_offer_year");
rdbV_statistic_order_offer_year.setDataSource(getDataSource());
rdbV_statistic_order_offer_year.setReadOnly(true);
rdbV_statistic_order_offer_year.open();

//LINE Chart
RemoteDataBook rdbV_statistic_order_offer_month = new RemoteDataBook();
rdbV_statistic_order_offer_month.setName("v_statistic_order_offer_month");
rdbV_statistic_order_offer_month.setDataSource(getDataSource());
rdbV_statistic_order_offer_month.setReadOnly(true);
rdbV_statistic_order_offer_month.setMasterReference(
                                      new ReferenceDefinition(new String[] { "YEAR_" },
                                                              rdbV_statistic_order_offer_year,
                                                              new String[] { "YEAR_" }));
rdbV_statistic_order_offer_month.open();

Both remote databooks are connected to a remote storage, identified by name (v_statistic_order_offer_year, v_statistic_order_offer_month). The storages are defined as server objects:

//Name: v_statistic_order_offer_year (BAR CHART)
DBStorage dbsV_statistic_order_offer_year = new DBStorage();
dbsV_statistic_order_offer_year.setWritebackTable("v_statistic_order_offer_year");
dbsV_statistic_order_offer_year.setDBAccess(getDBAccess());
dbsV_statistic_order_offer_year.open();

//Name: v_statistic_order_offer_month (LINE CHART)
DBStorage dbsV_statistic_order_offer_month = new DBStorage();
dbsV_statistic_order_offer_month.setWritebackTable("v_statistic_order_offer_month");
dbsV_statistic_order_offer_month.setDBAccess(getDBAccess());
dbsV_statistic_order_offer_month.open();

Both storages read data from database views (instead of tables). The views are not magic and could also be simple tables, but our Demo ERP has views for demonstration purposes.

Here's the definition of the view, used for the BAR chart:

CREATE OR REPLACE VIEW v_statistic_order_offer_year AS
SELECT ofe.YEAR_ AS YEAR_,
       sum(ofe.GROSSTOTALPRICE) AS OFFER_GROSSTOTALPRICE,
       sum(case when ord.GROSSTOTALPRICE IS NULL
                then 0
                else ord.GROSSTOTALPRICE
           end) AS ORDER_GROSSTOTALPRICE
  FROM (v_statistic_offer ofe
        LEFT JOIN v_statistic_order ord
               ON (((ofe.YEAR_ = ord.YEAR_) AND (ofe.MONTH = ord.MONTH))))
 GROUP BY ofe.YEAR_;

That's it. It's really simple to bind a JavaFX chart to a database table or view.

From Swing to Vaadin?

Some days ago, vaadin released a Tutorial for Swing developers. It's a hitchhiker's guide to convert a Swing app to modern web app. It's a must-read if you plan to replace/migrate or modernize your Swing application.

We were mentioned in the last paragraph with our JVx framework, as possible conversion strategy. Thanks for that!

I want to hook in at this paragraph, because I totally agree with the rest of the tutorial.

It's true that a wrapper has pros, cons and limitations. You can't wrap everything. Sure you could try, but it needs so many developers and doesn't make sense because a wrapper shouldn't copy the underlying technology. The more features the wrapper has, the more problems will occur with new (different) technologies. The wrapper should be a subset of all technologies. But a subset is limited in functionality!

A wrapper should be focused on a specific domain, e.g. database/data driven applications or game development. A wrapper for multiple domains will fail!

I don't know many working wrappers. There were many attempts to create (UI) wrappers, in the past, but most were stopped because of complexity or the developers had other interests (if project was open source).

JVx is one working solution and in my opinion the most complete one because it contains an UI wrapper, has implementations for different technologies like Swing, JavaFX, Headless and Vaadin. The APIs are bulletproof and there are native applications for Android and iOS. JVx is a generic solution and doesn't generate additional source code.
But it has more than that, because it's full-stack and comes with different application frames for desktop, web and mobile applications.

But what is your advantage if you're using a wrapper?

You're (GUI) technology independent.

An example:

Your current business application is a Swing application and you plan the migration to a modern technology.
Your first migration decision should be: Desktop or Web
Next decision: which UI framework
Optional: Mobile support?

If your platform decision was: Desktop, then it's very simple to find the right UI framework: JavaFX and try JavaFXPorts for mobile support.
Fact: No real web and possible problems with mobile support

If your platform decision was: Web, then it's not an easy task to find the right UI framework, but vaadin should be the first choice because it's comparable to Swing and hides web technology for you!
Fact: No desktop but mobile support

Every decision has pros and cons. If you bet on one technology stack, you're fixed to this technology stack. In our example it was JavaFX or vaadin. And what will be the next preferred UI technology after JavaFX or vaadin?
You'll have the same problems again and it's never easy to migrate a (business) application.

You should bet on a technology independent solution, to be prepared for the future!
Means, you should use a wrapper. But don't use a wrapper which hides the technology from you. It should be possible to access the technology directly - if needed or if it's not important to be technology independent.

Sometimes it's not possible to be technology independent, e.g. some custom controls aren't available for all technologies.

The wrapper should allow technology dependent and independent development without any limitations!

Does it make sense to use the same application with different technologies?

Yes, but...

It's not a good idea to use e.g. Swing AND JavaFX because both technologies are desktop toolkits. But it makes sense to use JavaFX for your backend application and vaadin for your frontend or your mobile devices.

It's also a good idea to create only one application that works as desktop, web and mobile application - the same application. But show different screens/views on different platforms.

There's no big difference between desktop and a standard browser because resolution of a desktop pc is the same. A mobile browser has limited space and you shouldn't use the same screen/view on a mobile device as on the desktop pc.

Example
We use an ERP backend application to manage vacations. The appliation has about 10 screens for resource management, master data management and accounting. The application runs as desktop application with JavaFX. The same application runs in desktop browsers with 3 screens because the web frontend doesn't offer master data management and accounting. The same application runs on mobile devices with only 1 screen because mobile devices are used from employees to enter and view vacations.

We have only one application, started with different UI technologies and with different screens/views.

It would be possible to create 3 different applications with different screens and with dependencies between the applications and ... (complex to maintain, 3 different projects, application frame x 3).

If you'll create a "native" vaadin application and a JavaFX application you'll need different development teams with different know-how.

Don't waste time and resources, focus on the real problems of your application. A wrapper hides technology problems and allows fast development with few developers: Win-win situation!

JavaFX, JVx, CalendarFX and Exchange Server

It's friday, and it's (still) sunny :)

Some days ago, CalendarFX was released. It's a commercial product and looks promising. Now and then, we play around with new commercial products/libraries because our dev teams should know which product will work in commercial projects. A calendar control is always useful and especially if you organize "something". Many ERP products do this.

In good old swing applications, we did use migcalendar for better UX and visualization. But it's not available for JavaFX, so we tried CalendarFX.

The control is still in an early development stage and has some bugs or missing APIs, but it's very polished and works great with JVx and our JavaFX UI:

JVx, JavaFX UI and CalendarFX

JVx, JavaFX UI and CalendarFX

We tried to implement a simple JavaFX calendar screen, for Outlook appointments. We already had a connector for Exchange servers, based on EWS Java API and our JVx' storage implementation.

The screen code was simple, and more or less a simply copy/paste of a CalendarFX tutorial application. Here it is:

private void initializeUI() throws ModelException
    {
        CalendarView calendarView = new CalendarView();
       
        Calendar work = new Calendar("Work");
        Calendar home = new Calendar("Home");

        work.setStyle(Style.STYLE1);
        home.setStyle(Style.STYLE2);

        CalendarSource calSources = new CalendarSource("Private");
        calSources.getCalendars().addAll(work, home);

        calendarView.getCalendarSources().addAll(calSources);

        calendarView.setRequestedTime(LocalTime.now());

        Thread updateTimeThread = new Thread("Calendar: Update Time Thread")
        {
            @Override
            public void run()
            {
                while (true)
                {
                    Platform.runLater(() ->
                    {
                        calendarView.setToday(LocalDate.now());
                        calendarView.setTime(LocalTime.now());
                    });

                    try
                    {
                        // update every 10 seconds
                        sleep(10000);
                    }
                    catch (InterruptedException e)
                    {
                        e.printStackTrace();
                    }

                }
            };
        };

        Thread thLoadData = new Thread(new Runnable()
        {
            public void run()
            {
                try
                {
                    RemoteDataBook rdb = new RemoteDataBook(apps);
                    rdb.setDataSource(getDataSource());
                    rdb.setName("calendar");
                    rdb.open();
                    rdb.fetchAll();
                   
                    ZonedDateTime zdt;
                   
                    for (int i = 0; i < rdb.getRowCount(); i++)
                    {
                        IDataRow row = rdb.getDataRow(i);
                       
                        Entry entry = new Entry(row.getValueAsString("SUBJECT"));
                       
                        zdt = ((Date)row.getValue("BEGIN")).toInstant().
                                     atZone(ZoneId.systemDefault());
                       
                        entry.setStartDate(zdt.toLocalDate());
                        entry.setStartTime(zdt.toLocalTime());
                       
                        if (((Boolean)row.getValue("ALLDAY")))
                        {
                            entry.setFullDay(true);
                            entry.setEndDate(entry.getStartDate());
                        }
                        else
                        {
                            zdt = ((Date)row.getValue("END")).toInstant().
                                         atZone(ZoneId.systemDefault());                                                        
                            entry.setEndDate(zdt.toLocalDate());
                            entry.setEndTime(zdt.toLocalTime());
                        }
                       
                        if (((Boolean)row.getValue("PRIVATE")))
                        {
                            Platform.runLater(() -> home.addEntry(entry));
                        }
                        else
                        {
                            Platform.runLater(() -> work.addEntry(entry));
                        }
                    }
                }      
                catch (Exception e)
                {
                    e.printStackTrace();
                }
            }
        });
       
        thLoadData.start();
        updateTimeThread.start();
       
        ((FXInternalWindow)getResource()).setContent(calendarView);
       
        setTitle("Calendar FX Demo");
    }

The storage definition for fetching appointments was trivial:

AppointmentsStorage apps = new AppointmentsStorage();
apps.setURL(new URI("<url>"));
apps.setUserName("<username>");
apps.setPassword("<password>");
apps.open();

Not more code!

The special thing in our screen was the integration of a custom control. Usually, we would integrate it like this:

add(new UICustomComponent(calendarView));

but our custom component integration for JavaFX UI wasn't ready. No problem, because it's always possible to access the real UI resource in JVx. So we did:

((FXInternalWindow)getResource()).setContent(calendarView);

and everything was as expected. Sure, the screen won't work with Swing because we made a direct access to a JavaFX resource, but this was not relevant for our test :)

JVx 2.2

Today is a great day because I'm very happy to announce JVx - version 2.2.
It's an awesome release with soo many new features.

First of all, the LoC analysis. Here are some very interesting numbers for you:

JVx library   Swing UI
LoC   Type
73.759   Code
62.025   Comments (~ 46% of Code)
19.662   Empty lines
155.446   Total
LoC   Type
34.032   Code
18.882   Comments (~ 36% of Code)
7.662   Empty lines
60.576   Total
 
JVx library (Test cases)  
LoC   Type
21.093   Code
11.441   Comments (~ 35% of Code)
7.300   Empty lines
39.834   Total

Not bad if you compare it with other releases: 0.8, 1.0, 2.0.
We've still a very small codebase, compared to the features. The code quality and test coverage are still "green".

Some additional numbers:

Files and Tests
JVx library source files   594
Swing UI source files   135
Test source files   140
Total   869
Still a small codebase ;) and still very easy to maintain. Here are more numbers, about testing:
 
Unit tests (no UI, without manual perf. tests)   958
Class coverage (without UI)   81%
Method coverage (without UI)   69%
Our coverage got better since 2.0 - well done.

TOP 10 classes

Classname   LoC
MemDataBook 4.028
DBAccess 3.772
JVxTable 2.510
ArrayUtil 2.224
StringUtil 1.738
Server 1.715
DBStorage 1.542
JVxFormLayout 1.243
FileUtil 1.182
SwingApplet 1.102

Sure, MemDataBook and DBAccess are our main classes but we should check if it'll be possible to reduce complexity!

And last but not least, a short overview of new features:

  • Performance tuning
    JVx got a boost. We pimped our model to be super fast. Sure, it was fast and we didn't have any problems... but during some code reviews, we found some lacks because of gc calls. The memory consumption wasn't perfect and not gc friendly. We created a lot of temporary String[] and event objects, even if the weren't needed.

    Long story, short: Inserting 2.000.000 records with 16 columns was done in about 23 seconds. Now: 1.5 seconds.

  • Support for IoT/M2M/Microservices

    We pimped our remote communication a little bit. It's now possible to embedd JVx, especially the server class, in any environment that supports Java. We had an implementation for Java application serves like Tomcat or Wildfly, but no solution for plain socket servers. We put a lot of work in this part of JVx. We now have out-of-the-box solutions for vert.x or plain socket servers. It've never been easier to write remote applications with JVx.

  • Better JNDI support

    We had JNDI support since JVx 1, but now it's bulletproof. Use JNDI to configure your database connection or the whole application. It's possible to load application config.xml via JNDI. Same is valid for server configuration. We allow, so called, virtual configurations.

  • @PostConstruct and @PreDestroy

    We've support for both annotations in our server-side Lifecycle objects. It's now possible to remove your workarounds like:

    if (getClass() == Application.class)

    to find out whether the application LCO or session LCO was created. The session LCO extends the application LCO and otherwise it wasn't possible to do things only if application LCO was created, because constructor was called for every session LCO again.

  • Lambda support

    It's soo much fun, working with lambdas and Java 8. We're happy to have full support for lambda expressions in JVx especially for event listener handling. And it's backwards compatible (Java 6, 7) without restrictions.
    Be sure that you recompile your JVx projects with JVx 2.2 library.

  • Log4j support

    We love using built-in Java APIs like Logging API - because it doesn't need extra libraries. But we're open for 3rd party libraries and log4j(2) is too popular to ignore it. So we have official support for it in JVx. Simply use the new log factory com.sibvisions.util.log.log4j.Log4jLoggerFactory for your application and configure your loggers via log4j.properties or log4j2.xml.

  • Spring security

    We had a customer request for supporting SAML 2.0 authentication. SAML what?
    Yes, we had the same question, but found that Spring framework had a solution for it: Spring Security SAML. We didn't reinvent the wheel and connected Spring security with our security mechanism. Here's the source code.

  • HanaDBAccess

    HANA is the in-memory db solution of SAP. We've a connector for it. But be careful, because we weren't allowed to tune the database :)

  • Bugfixes

The list isn't complete but contains some important features. The full changelog is available here.

Drag'n'Drop support for JavaFX' TabPane

We're currently working on our JavaFX UI for JVx. We're making good progress but sometimes, missing JavaFX functionality stops us, e.g. We need a Tab Pane with Drag and Drop support for Tabs. There's no support in current Java 8 versions :(

But Tom Schindl had the same requirement for his e(fx)clipse project. We thought that his implementation could be a simple solution for us as well!

But nothing is soo easy.

Our first problem was that we didn't need the whole project because it has "some dependencies" and consists of different jar files. So we thought that it would be a good idea to use only the relevant classes. Not so simple because of the license (EPL). The source code integration in our project wasn't possible, because we're Apache 2.0 licensed. But it was allowed to use some classes, create a new project with EPL and add the library to our project (thanks Tom for sharing your thoughts with us).
The result is our javafx.DndTabPane project, hosted on github.

The implementation of Tom worked great, but we had some extra requirements for our API:

  • Don't drag disabled tabs
  • It should be possible to disable dragging
  • Event if dragging

Sure, we made some smaller changes to allow customization.

In addition to Drag and Drop support, we found two problems with standard TabPane: RT-40149 and RT-40150.

We have one workaround and one dirty fix for the problems in our UI implementation: RT-40149 and RT-40150. (Not proud of it, but works)

News mix

The next release of JVx is coming!

It'll be version 2.2. We have 2 open tickets for this release but both are refactoring tasks, nothing too important. We're already feature complete.

It'll be an awesome release because we have a lot of performance improvements and some really cool features like lazy loading of BLOBs (binary content). The server implementation is now IoT ready and it's pluggable. Support for Lambda expressions with full backwards compatibility for our listener handling. And we have support for application monitoring, style definitions, streamed upload of large files, and much more.

We plan the release for the end of this week.

Our VaadinUI was based on vaadin 7.1.15 and 7.4 was released some days ago. We're happy to announce support for vaadin 7.4.

The repository of JVx' vaadin UI already contains 7.4 libraries and everything is available for you. We don't have an official release right now, because we do some tests and afterwards we'll release a new version of our UI. We don't have a date for you but hopefully in March.

We currently don't use the new Grid component, but we'll replace the current table implementation asap.

The last information is about the next release of VisionX 2.2 preview. It will contain JV' vaadin UI for vaadin 7.4 and some new features like exporting an application for embedded devices (run the application on embedded devices like Raspberry Pi, without application server - "Micro applications").

Oh, finally... Check our github page, because we have new projects for you.