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: Vaadin

VisionX, JVx and native Vaadin

If you create an application with VisionX, it's always a JVx based application. You get all advantages of JVx and its GUI independency, but sometimes the GUI indepency is not important and you want to use native GUI controls in your JVx application because JVx doesn't contain the GUI control or you need a commercial control. This is a very simple use-case and it's not a problem to mix JVx components with native components. We have different examples, with different GUI technologies, for this use-case.

Here are some links:

But we don't have a link for our Vaadin implementation. But no problem, here it is!

Simply create a new application with VisionX and a dummy screen like this one:

Simple screen

Simple screen

The screen contains a simple table and two editors. Nothing special. Now we want to add a custom Vaadin component in the empty space. It doesn't matter which component you use. Every vaadin component or AddOn component can be used. JVx doesn't do specific things, it's only an UI abstraction layer.

So, lets add an Accordion to the screen:

Integrated Accordion

Integrated Accordion

The Accordion component is a standard Vaadin component, simply added to the screen. But more... Do you see the "Show Vaadin Notification" Button? This is a standard JVx component. So we mix native vaadin components with standard JVx components and get the full power of both. One advantage of the JVx components is that the automatic translation works without additional hacks, or what about JVx' layouts, event handling, ...

Interested in the source code?

No worries, it's super simple to understand :)

Lets have a look at the custom code:

UIButton butNotification = new UIButton("Show Vaadin Notification");
butNotification.eventAction().addListener(new IActionListener()
{
        public void action(UIActionEvent arg0) throws Throwable
        {
                Notification noti = new Notification("Message",
                                                     "Description", Type.WARNING_MESSAGE);
                noti.setDelayMsec(2000);
                noti.show(Page.getCurrent());
        }
});

UIFormLayout flJVxPanel = new UIFormLayout();

UIPanel panJVxPanel = new UIPanel();
panJVxPanel.setLayout(flJVxPanel);

panJVxPanel.add(butNotification);

if (getApplication().getLauncher().isWebEnvironment())
{
        Accordion acc = new Accordion();
        acc.setHeight(100.0f, Unit.PERCENTAGE);

        for (int i = 1; i < 8; i++)
        {

                if (i >= 2)
                {
                        final Label label = new Label("Welcome sheet!", ContentMode.HTML);
                        label.setWidth(100.0f, Unit.PERCENTAGE);

                        final VerticalLayout layout = new VerticalLayout(label);
                        layout.setMargin(true);

                        acc.addTab(layout, "Tab " + i);
                }
                else
                {
                        groupPanelOverview.add(panJVxPanel);

                        acc.addTab(((Component)panJVxPanel.getResource()), "Tab " + i);
                }
        }

        groupPanelOverview.add(new UICustomComponent(acc), formLayout1.getConstraints(0, 2, -1, -1));
}

The Accordion source code was copied from Vaadin Sampler:

sample = new Accordion();
sample.setHeight(100.0f, Unit.PERCENTAGE);
 
for (int i = 1; i < 8; i++) {
    final Label label = new Label(TabSheetSample.getLoremContent(), ContentMode.HTML);
    label.setWidth(100.0f, Unit.PERCENTAGE);
 
    final VerticalLayout layout = new VerticalLayout(label);
    layout.setMargin(true);
 
    sample.addTab(layout, "Tab " + i);
}

So, what are the most interesting parts in our code?

First, we add the JVx panel to another JVx panel. This is important to get support for translation. If it's not important for your, simply ignore the line:

groupPanelOverview.add(panJVxPanel);

The groupPanelOverview is a simple UIGroupPanel with UIFormLayout:

UIFormLayout formLayout1 = new UIFormLayout();

UIGroupPanel groupPanelOverview = new UIGroupPanel();

groupPanelOverview.setText("Overview");
groupPanelOverview.setLayout(formLayout1);

groupPanelOverview.add(labelName, formLayout1.getConstraints(0, 0));
groupPanelOverview.add(editOverviewName, formLayout1.getConstraints(1, 0));
groupPanelOverview.add(labelDescription, formLayout1.getConstraints(0, 1));
groupPanelOverview.add(editOverviewDescription, formLayout1.getConstraints(1, 1, -1, 1));

Our JVx button will be added to the native vaadin Accordion with following code:

acc.addTab(((Component)panJVxPanel.getResource()), "Tab " + i);

We don't add the JVx component itself, we use the wrapped resource. This is a simple vaadin component: com.vaadin.ui.Button

And finally, we add the Accordion as custom component to our JVx group panel:

groupPanelOverview.add(new UICustomComponent(acc), formLayout1.getConstraints(0, 2, -1, -1));

This code:

if (getApplication().getLauncher().isWebEnvironment())

is important for VisionX because the vaadin components aren't available in Swing, so we use this check for the supported environment.

So far, we mixed native vaadin components with JVx components. It's super easy to use, isn't it?

But it's also possible to use CSS for JVx components:

Css style for Button

Css style for Button

The button got the friendly style, which is defined in Vaadin CSS. Check some examples.

To add the friendly style class to the JVx button, simple add:

Style.addStyleNames(butNotification, "friendly");

This example is using predefined CSS from vaadin. It's also possible to set custom styles in your own css file. Simple follow this instructions.

This article covered the integration of native vaadin components into an existing JVx application with all advantages of vaadin.

Vaadin, let's hack the Profiler

Vaadin comes with a builtin Profiler which is only available during debug mode, which might not be available or reasonable. So, let us see if we can use it without the debug mode enabled.

It has a profiler?

Yes, there is one right builtin on the client side. You can activate it easily enough by adding the following to the widgetset:

  1. <set-property name="vaadin.profiler" value="true" />

But to see the results, you also have to switch the application into debug mode by changing the web.xml to the following:

  1. <context-param>
  2.     <description>Vaadin production mode</description>
  3.     <param-name>productionMode</param-name>
  4.     <param-value>false</param-value>
  5. </context-param>

This allows you to enter the debug mode of an application, though, that requires to restart the application (or in the worst case, a redeploy). One upside of testing new Widgetsets can be that one can apply them to any running application without modifications, because that is purely client-side. So changing the configuration of the application might not be possible or desirable.

There are some forum posts out there which talk about that it is enough to enable the profiler and see the the output of it being logged to the debug console of the browser, but that is not the case anymore.

Let's have a deeper look

The Profiler can be found in the class com.vaain.vaadin.client.Profiler and is comletely client-side. It will store all gathered information until the function logTimings() is called, which then will hand the gathered information to a consumer which can do with it whatever it wants. Now comes the interesting part, there is no public default implementation for the consumer provided. If you want to log what was profiled to the debug console you'll have to write your own. Even if there were, the function setProfilerResultConsumer(ProfilerResultConsumer) is commented with a warning that it might change in future versions without notice and should not be used - interesting. Also interesting is the fact that it can only be set once. Once set, it can not be changed.

Hm, looks a little bare bone. Of course there is an "internal" class that is utilizing it to send its output to the debug window, but we can't use any of that code, unfortunately. So let's see what we can do with it.

Send everything to the debug console

The easiest thing is to simply send all the output to the debug console of the browser, we can do this easily enough:

  1. import java.util.LinkedHashMap;
  2. import java.util.List;
  3.  
  4. import com.vaadin.client.Profiler.Node;
  5. import com.vaadin.client.Profiler.ProfilerResultConsumer;
  6.  
  7. /**
  8.  * A simple {@link ProfilerResultConsumer} which is outputting everything to the
  9.  * debug console of the browser.
  10.  *
  11.  * @author Robert Zenz
  12.  */
  13. public class DebugConsoleProfilerResultConsumer implements ProfilerResultConsumer
  14. {
  15.     //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  16.     // Initialization
  17.     //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  18.    
  19.     /**
  20.      * Creates a new instance of {@link DebugConsoleProfilerResultConsumer}.
  21.      */
  22.     public DebugConsoleProfilerResultConsumer()
  23.     {
  24.         super();
  25.     }
  26.    
  27.     //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  28.     // Interface implementation
  29.     //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  30.    
  31.     /**
  32.      * {@inheritDoc}
  33.      */
  34.     @Override
  35.     public void addProfilerData(Node pRootNode, List pTotals)
  36.     {
  37.         debug(pRootNode);
  38.        
  39.         for (Node node : pTotals)
  40.         {
  41.             debug(node);
  42.         }
  43.     }
  44.    
  45.     /**
  46.      * {@inheritDoc}
  47.      */
  48.     @Override
  49.     public void addBootstrapData(LinkedHashMap pTimings)
  50.     {
  51.         // TODO We'll ingore this for now.
  52.     }
  53.    
  54.     //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  55.     // User-defined methods
  56.     //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  57.    
  58.     /**
  59.      * Sends the given {@link Node} to the debug console if it is
  60.      * {@link #isValid(Node) valid}.
  61.      *
  62.      * @param pNode the {@link Node} to log.
  63.      * @see #isValid(Node)
  64.      */
  65.     private void debug(Node pNode)
  66.     {
  67.         if (isValid(pNode))
  68.         {
  69.             debug(pNode.getStringRepresentation(""));
  70.         }
  71.     }
  72.    
  73.     /**
  74.      * Tests if the given {@link Node} is valid, meaning not {@code null}, has a
  75.      * {@link Node#getName() name} and was {@link Node#getCount() invoked at
  76.      * all}.
  77.      *
  78.      * @param pNode the {@link Node} to test}.
  79.      * @return {@code true} if the given {@link Node} is considered valid.
  80.      */
  81.     private boolean isValid(Node pNode)
  82.     {
  83.         return pNode != null && pNode.getName() != null && pNode.getCount() > 0;
  84.     }
  85.    
  86.     //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  87.     // Native methods
  88.     //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  89.    
  90.     /**
  91.      * Logs the given message to the debug console.
  92.      *
  93.      * @param pMessage the message to log.
  94.      */
  95.     private native void debug(String pMessage)
  96.     /*-{
  97.         console.debug(pMessage);
  98.     }-*/;
  99.    
  100. }    // DebugConsoleProfilerResultConsumer

And we can attach it rather easily, too:

  1. Profiler.setProfilerResultConsumer(new DebugConsoleProfilerResultConsumer());

Make sure to do this only once, otherwise an Exception will be thrown, stating that it can only be done once. Also the application should not be in debug mode, otherwise the Vaadin consumer will be attached. Now that we've attached a consumer we can recompile the Widgetset and actually try it, and low and behold, we see output in the debug window of the browser. Quite a lot, actually, seems like the Profiler is used often, which is good.

Filter the results

Skimming through the results is tedious, luckily most browsers come with the possibility to filter the results, but that possibility is quite limited. If we are interested in multiple results, the easiest way will be to filter them on the server side, obviously we can do that just as easily:

  1. import java.util.HashSet;
  2. import java.util.LinkedHashMap;
  3. import java.util.List;
  4. import java.util.Set;
  5.  
  6. import com.vaadin.client.Profiler.Node;
  7. import com.vaadin.client.Profiler.ProfilerResultConsumer;
  8.  
  9. /**
  10.  * A simple {@link ProfilerResultConsumer} which is outputting everything to the
  11.  * debug console of the browser.
  12.  *
  13.  * @author Robert Zenz
  14.  */
  15. public class DebugConsoleProfilerResultConsumer implements ProfilerResultConsumer
  16. {
  17.     //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  18.     // Class members
  19.     //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  20.    
  21.     /** The names of nodes we want to output. */
  22.     private Set wantedNames = new HashSet();
  23.    
  24.     //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  25.     // Initialization
  26.     //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  27.    
  28.     /**
  29.      * Creates a new instance of {@link DebugConsoleProfilerResultConsumer}.
  30.      *
  31.      * @param pWantedNames the names of the profiler data which should be
  32.      *            displayed.
  33.      */
  34.     public DebugConsoleProfilerResultConsumer(String... pWantedNames)
  35.     {
  36.         super();
  37.        
  38.         if (pWantedNames != null && pWantedNames.length > 0)
  39.         {
  40.             for (String wantedName : pWantedNames)
  41.             {
  42.                 wantedNames.add(wantedName);
  43.             }
  44.         }
  45.     }
  46.    
  47.     //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  48.     // Interface implementation
  49.     //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  50.    
  51.     /**
  52.      * {@inheritDoc}
  53.      */
  54.     @Override
  55.     public void addProfilerData(Node pRootNode, List pTotals)
  56.     {
  57.         debug(pRootNode);
  58.        
  59.         for (Node node : pTotals)
  60.         {
  61.             debug(node);
  62.         }
  63.     }
  64.    
  65.     /**
  66.      * {@inheritDoc}
  67.      */
  68.     @Override
  69.     public void addBootstrapData(LinkedHashMap pTimings)
  70.     {
  71.         // TODO We'll ingore this for now.
  72.     }
  73.    
  74.     //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  75.     // User-defined methods
  76.     //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  77.    
  78.     /**
  79.      * Sends the given {@link Node} to the debug console if it is
  80.      * {@link #isValid(Node) valid}.
  81.      *
  82.      * @param pNode the {@link Node} to log.
  83.      * @see #isValid(Node)
  84.      */
  85.     private void debug(Node pNode)
  86.     {
  87.         if (isValid(pNode))
  88.         {
  89.             debug(pNode.getStringRepresentation(""));
  90.         }
  91.     }
  92.    
  93.     /**
  94.      * Tests if the given {@link Node} is valid, meaning not {@code null}, has a
  95.      * {@link Node#getName() name} and was {@link Node#getCount() invoked at
  96.      * all}.
  97.      *
  98.      * @param pNode the {@link Node} to test}.
  99.      * @return {@code true} if the given {@link Node} is considered valid.
  100.      */
  101.     private boolean isValid(Node pNode)
  102.     {
  103.         return pNode != null
  104.                 && pNode.getName() != null
  105.                 && pNode.getCount() > 0
  106.                 && (wantedNames.isEmpty() || wantedNames.contains(pNode.getName()));
  107.     }
  108.    
  109.     //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  110.     // Native methods
  111.     //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  112.    
  113.     /**
  114.      * Logs the given message to the debug console.
  115.      *
  116.      * @param pMessage the message to log.
  117.      */
  118.     private native void debug(String pMessage)
  119.     /*-{
  120.         console.debug(pMessage);
  121.     }-*/;
  122.    
  123. }    // DebugConsoleProfilerResultConsumer

Now we can simply pass the list of "interesting" event names to the consumer and see only these.

JavaScript hacking

But there is more, instead of setting a consumer we can attach ourselves to the JavaScript function and instead process each profiled section individually. So in the debug console we can simply run something like this:

  1. window.__gwtStatsEvent = function(event)
  2. {
  3.     console.debug(event);
  4. };

This will output every single profiler event into the console. Now, if we want to process these events, we must first understand there is always a "begin" and an "end" event, which respectively are marking the begin and end of an event.

We can now listen for a certain event and simply output how long it took, like this:

  1. window.__profiler = {};
  2.  
  3. window.__gwtStatsEvent = function(event)
  4. {
  5.     if (event.subSystem === "Layout pass")
  6.     {
  7.         if (event.type === "begin")
  8.         {
  9.             window.__profiler[event.subSystem] = event.millis;
  10.         }
  11.         else
  12.         {
  13.             console.log(
  14.                     event.subSystem
  15.                     + ": "
  16.                     + (event.millis - window.__profiler[event.subSystem]).toFixed(0)
  17.                     + "ms");
  18.         }
  19.     }
  20. };

Or, to go over the top, we could create a generic listener which informs us about everything:

  1. window.__wantedEvents = [
  2.     "Layout pass",
  3.     "Layout measure connectors",
  4.     "layout PostLayoutListener"
  5. ];
  6.  
  7. window.__profiler = {};
  8.  
  9. window.__gwtStatsEvent = function(event)
  10. {
  11.     if (window.__wantedEvents.indexOf(event.subSystem) >= 0)
  12.     {
  13.         if (typeof window.__profiler[event.subSystem] === "undefined")
  14.         {
  15.             window.__profiler[event.subSystem] = {
  16.                 averageRuntime : 0,
  17.                 count : 0,
  18.                 lastBegin : 0,
  19.                 lastEnd : 0,
  20.                 lastRuntime: 0,
  21.                 lastRuntimes : new Array(),
  22.                 minRuntime : 999999999,
  23.                 maxRuntime : -999999999,
  24.                 totalRuntime : 0
  25.             }
  26.         }
  27.        
  28.         var info = window.__profiler[event.subSystem];
  29.        
  30.         if (event.type === "begin")
  31.         {
  32.             info.count = info.count + 1;
  33.             info.lastBegin = event.millis;
  34.         }
  35.         else
  36.         {
  37.             info.lastEnd = event.millis;
  38.            
  39.             info.lastRuntime = info.lastEnd - info.lastBegin;
  40.             info.lastRuntimes.push(info.lastRuntime);
  41.             info.minRuntime = Math.min(info.lastRuntime, info.minRuntime);
  42.             info.maxRuntime = Math.max(info.lastRuntime, info.maxRuntime);
  43.             info.totalRuntime = info.totalRuntime + info.lastRuntime;
  44.            
  45.             info.averageRuntime = 0;
  46.             for (var index = 0; index < info.lastRuntimes.length; index++)
  47.             {
  48.                 info.averageRuntime = info.averageRuntime + info.lastRuntimes[index];
  49.             }
  50.             info.averageRuntime = info.averageRuntime / info.lastRuntimes.length;
  51.            
  52.             console.log(
  53.                     event.subSystem
  54.                     + ": "
  55.                     + info.count.toFixed(0)
  56.                     + " times at "
  57.                     + info.averageRuntime.toFixed(3)
  58.                     + " totaling "
  59.                     + info.totalRuntime.toFixed(0)
  60.                     + "ms with current at "
  61.                     + info.lastRuntime.toFixed(0)
  62.                     + "ms ("
  63.                     + info.minRuntime.toFixed(0)
  64.                     + "ms/"
  65.                     + info.maxRuntime.toFixed(0)
  66.                     + "ms)");
  67.         }
  68.     }
  69. };

And we now have a neat little system in place which displays everything we'd like to know, and it is easily extendable and modifiable, too.

Conclusion

As we see, we have quite a few ways to get the information from the profiler even without the application running in debug mode, some might not be as obvious as others, though. The interesting part is that many things are easily accessible on the JavaScript side of Vaadin, directly from the debug console of the browser, one only has to look for it.

Map component for JVx applications

We played around with some interesting stuff in the last weeks. Some customers and users asked us if we have a Map component.

We don't have a ready-to-use component but there are many free and commercial solutions available. The integration in a JVx application with custom components is not a problem and doesn't need much effort. But sure, an out-of-the-box solution would be useful.

Our Research team did create a PoC for a Map. The results is very nice and we want to show you some screenshots from our tests.

Swing integration (Tab mode)

Swing integration (Tab mode)

Swing integration (frame mode)

Swing integration (frame mode)

Vaadin integration

Vaadin integration

Vaadin integratin (corporation mode)

Vaadin integratin (corporation mode)

We didn't add the component to JVx because it's just a PoC and not ready-to-use.
But the Map integration looks great :)

The future of JavaFX?

After one year of JavaFX development, we thought it's time to write about our experience.

We started in Nov. 2014 with our first bigger JavaFX tests. The idea was an UI implementation for JVx. We thought it should be an easy task because JavaFX is a desktop technology. We had another research project in 2012, but the result wasn't as expected. Sometimes it's a good idea to re-start from scratch!

JavaFX wasn't very popular and is still not a Superstar, but we love researching and we thought it might be a good idea to bet on JavaFX. Not only as pure desktop solution and Swing replacement, but also for mobile app development based on JavaFXPorts and for embedded devices, like Raspberry Pi. So we had this big picture in mind.
We thought it would be awesome to create a single JavaFX application, for all platforms and devices. Sure, some other companies tried to solve this problem as well, but we didn't try to do the same. Our idea was simple and based on JVx. We hade this awesome JVx application framework which enabled GUI and technology independent application development. So we tried to solve the GUI problem because all other things like persistence, remote communcation, i18n, ... were already solved by JVx.

We did different GUI implementations for JVx, before we started with JavaFX. Our first one was based on Swing, followed by QTJambi, GWT, GXT, a headless variant and - last but not least - vaadin. We also made some tests with Flex and Pivot, but we didn't create more than some simple PoC. To be clear: GUI technology know-how was not the problem!

We knew that JavaFX didn't have a solution for MDI and especially a DesktopPane was missing, but it wasn't a problem to create custom components/controls. We had some hard months of development because we found out that JavaFX wasn't a mature toolkit like Swing. We had to find many workarounds for very simple problems and had to create more custom components than expected. We solved most problems in our own code, but it wasn't possible to change some basic problems. We tried to get in contact with the developers, via JIRA, but it was hard to explain real-world use-cases to toolkit developers. Our developers at SIB Visions create custom products and projects together with customers for their needs. So we had many UI toolkit requirements from real users. Some issues were accepted but not all. Many bugs were fixed but we had big problems with Feature Requests. So far so good.

We finished our JavaFX UI implementation in April 2015 and it was a big success, because we had a fresh UI technology with lots new features and animations, transitions, web and media views, .... awesome.

We thought that JavaFX will be improved in 2015/2016 and it will be mature enough to use it for our customers.

Wait... what's the problem with JavaFX?

Performance, Memory, limited chances to modify standard controls

The performance is not good, if you have many controls (= nodes). It's different on Windows, Linux, MacOS. It's much better on MacOS than on any other supported OS. If you develop business/backoffice applications, the performance is very important. Sure, if you create simple form based applications, it doesn't really matter.

We use JVx to develop huge backoffice applications and currently, JavaFX should be used with care.

What do we mean with "performance is not good"?

  • Large TableViews have scroll delays
  • Layouting sometimes need some "extra repaints"
  • Scrolling with many controls is not immediate
  • Startup time of an application is too long, compared to e.g. Swing applications

The version number of JavaFX 8 is too high for it's maturity.

JavaFX has big potential but we're not sure if it'll survive it's predecessor Swing.

And we're not alone with our opinion: Should Oracle Spring clean JavaFX

But there are also companies with JavaFX applications: JavaFX Real-world apps

There's more

The toolkit issues are one thing. Another big surprise was that Oracle stopped official ARM support in Jan 2015 which didn't mean that JavaFX doesn't run on ARM devices (RaspberryPi, ...), but it's not officially supported and Oracle doesn't fix bugs or implement improvements.
Thanks to Gluon it's still very easy to use JavaFX on ARM devices.

Another step backwards was the migration to Bugzilla. In 2014 (and earlier), JavaFX was a "newcomer" and announced as Swing replacement. The development process at Oracle was very open and you had a "direct connection" to the development team, or something like that. It was very simple to report issues and to get feedback from the developers. It was fantastic to see and feel the progress. This is different nowadays, because the ticketing system moved from JIRA to Bugzilla and it's more or less readonly for standard developers.

One problem with JavaFX is that Oracle doesn't tell us the strategy behind JavaFX. The investment of Oracle in JavaFX was high, but what will be the next step? It's hard to bet on JavaFX without definitive commitment from Oracle.

But we still hope that JavaFX will be the one and only UI toolkit for Java.

JavaFX for Android and iOS

In summer, we moved forward and tried to use JavaFXPorts. It makes it possible to use your JavaFX application as native Android and iOS apps. Our JavaFX UI worked with some smaller changes out-of-the-box. It was awesome to see our JVx on Android or iOS devices! It was a milestone.

But things have changed since summer because JavaFXPorts has a depency on RoboVM. It was an OpenSource project and was a big win for the community. But now it's a commercial tool (read more). This has no impact for us, but means that we can't offer an out-of-the-box OpenSource solution.

JavaFXPorts also works without RoboVM and there are plans for a JVM running on mobile devices, but this won't solve the problem that you need access to device features/APIs. But we'll see what happens in the next few months.

We had some fun in the last few weeks because we tuned our application frame for mobile devices. A mobile application has some specific characteristics and isn't a 1:1 desktop application. A desktop application usually has a menubar and a toolbar. The same app on a mobile device shouldn't use a menubar or toolbar. It should offer a hamburger button which offers a custom menu. Also the style of the controls should be different on mobile devices, e.g. Tabsets.

There are two interesting projects which offer custom mobile controls. The first is a commercial product, from Gluon and the second one is JFoenix and it's OpenSource (LGPL). We took JFoenix because it met our requirements and JVx is OpenSource.

We have some screenshots in older posts:

Resume

JavaFX has potential to rule the Java UI world, but it needs an official commitment/statement from Oracle. Now it's unclear if JavaFX is the right UI technology for the future.

We hope that JavaFX is the right toolkit, but we aren't sure. Our investment was risky and high, but no risk - no fun. The results are awesome!

Thanks to JVx the UI technology is not important for us, because if JavaFX won't make the race, we still have Swing or vaadin. It's important to be UI technology independent because it saves time and money and is future save.

VaadinUI without web.xml

We've added some annotations to our vaadin UI to support UI configuration without web.xml (deployment descriptor).

Check this:

@Push
@Widgetset(value = "com.sibvisions.rad.ui.vaadin.ext.ui.Widgetset")
@Configuration({@Parameter(name = "main", value = "MinimalApplication$MyApplication")})
@SuppressWarnings("serial")
public class MinimalApplication extends VaadinUI
{
    @WebServlet(value = {"/minimal/*", "/VAADIN/*"}, asyncSupported = true)
    @VaadinServletConfiguration(productionMode = false, ui = MinimalApplication.class)
    public static class Servlet extends VaadinServlet
    {}

    public static class MyApplication extends Application
    {
        public MyApplication(UILauncher pLauncher)
        {
            super(pLauncher);
           
            setName("JVx application");
            setLayout(new UIBorderLayout());
           
            add(new UILabel("Hello JVx' vaadinUI"), UIBorderLayout.CENTER);
        }        
    }
}

The example demonstrates a minimalistic JVx application with vaadin UI. It's like a standard vaadin application with one additional annotation:

@Configuration({@Parameter(name = "main", value = "MinimalApplication$MyApplication")})

The main parameter defines the JVx application class. It's the inner class MyApplication, in our example.

It's that easy!

Application Coder

This article is about our new Research project: Application Coder.

The application is a very simple Java Code Editor. It shows a tree with Java files and has a Code Editor for modifying files. The code editor is the popular Ace Editor and we use Eclipse JDT for java compilation. The application was written as standard JVx application with vaadin UI.

We made tests as single-page vaadin application, embedded with iframes and embedded with div areas. All versions work without problems but the last one is preferred. If you embedd a vaadin application with divs, it's a little bit tricky because you have to configure the client-side on your own, but you get full access to the whole html page. This wouldn't be possible if you use an iframe because you can't access the main html page.

Some cool features of our editor are: error annotations and error markers. And the best feature is our LIVE Preview of code changes!

Annotations and marker

Annotations and marker


Watch this video:

Application coder


The application coder is not only a Java code editor, it was designed especially for JVx applications, because it groups client code and business logic. The preview also starts a JVx application and LIVE preview reloads the application.

Our coder application has a push mechanism and reloads every preview window automatically and immediate after compilation.

Above video shows multiple instances of our coder application, embedded in divs and it's possible to drag around and resize the applications (thanks to jquery-ui).

The application is a perfect showcase of JVx because it's not a database application as many other JVx applications. We've used vaadin, jquery-ui and vaadin-addons to create a great UX. JVx is technology independent and open for other technologies.

Style vaadin menubar popups

Our new application frame has two different vaadin menubars. One for the application menu and one as "hidden" menubar for the user options.

Here's a merged screenshot of both menubars:

Menubar popup

Menubar popup

As you can see, the left popup is dark and the right popup is bright. Usually, vaadin doesn't allow custom "additional" style definitions for menubar popups. The default style name is:

v-menubar-popup

The name is defined in the class com.vaadin.shared.ui.menubar.MenuBarState as

primaryStyleName = "v-menubar"

If you want to add an additional style class, it's simply not possible because the client implementation (com.vaadin.client.ui.VMenuBar) sets the primary style name, from the menubar, as style name for the popup overlay. The only thing you can do is, to change the primary stylename of your menubar. The problem is that you have to define all styles for the menubar-popup and menuitems, submenus, ... again in your style file. We tried it but it was horrible because you can't easily change the theme.

We tried to find a solution without changing vaadin client. We tried to set a primary style name as e.g. customstylepopup v-window-popup. But the client menu implementation has following code in getPrimaryStyleName:

protected static String getStylePrimaryName(Element elem) {
  String fullClassName = getStyleName(elem);

  // The primary style name is always the first token of the full CSS class
  // name. There can be no leading whitespace in the class name, so it's not
  // necessary to trim() it.
  int spaceIdx = fullClassName.indexOf(' ');
  if (spaceIdx >= 0) {
    return fullClassName.substring(0, spaceIdx);
  }
  return fullClassName;
}

(it makes sense to do this!)

So, it wasn't possible with simple tricks. The only solution - we found - was an extension of VMenuBar to override getPrimaryStyleName and return a custom style class concatenated with the default style class, something like this:

@Override
public String getStylePrimaryName()
{
    if (popupStyle != null)
    {
        return popupStyle + " " + super.getStylePrimaryName();
    }
       
    return super.getStylePrimaryName();
}

It wasn't our preferred solution, but we had another hack for setting ids of menu items. So it wasn't hard to add another hack for the style name :)

With our modification, it'll be possible to add custom style classes to menubar popups:

Custom style names

Custom style names

The source code is available on sourceforge.

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!

Vaadin application frame design

Many of you probably know our application frame, for web applications: One application, different styles

We had a MDI variant for legacy applications with internal frames for screens. This is useful for applications with many screens and many records. The internal frames help to compare records from one screen with records from other screens.

For modern user interfaces, we use the SDI option. It looks fresh and simple and is great for applications with a small number of screens, because a scrolling menu is not nice - sure it will scroll if needed.

But what about application with e.g. 60 screens. Is MDI the only option? Yes and No, because we didn't have a variant for that kind of applications.... but now we have.

It's a mix of MDI and SDI, with a little bit CI:

Application frame SDI with menu

Application frame SDI with menu

The application frame is still the same as before, but with a different option. The name of the option is corporation, because the UI is meant for applications with many screens. It's still SDI with modal popups, because it shouldn't be too legacy!

Oh, do you see the small buttons on top/right? We use the FontAwesome feature of vaadin 7.2. We're already using vaadin 7.4.2 for our JVx vaadin UI!

We now have one application frame for many different application styles (I don't talk about visual attributes). The application frame is responsive and works well on mobile devices.

JVx and JavaFX (fasten your seat belts)

Today is a great day, because I'm able to write about our latest Research Project.
It has to do with JavaFX and JVx - what else.

If you remember one of my blog postings in 2013, you know that we tried to implement our JVx UI with JavaFX. Long story, short: Not possible with one master thesis.

But... we always try to reach our goals and it's an honor to tell you that we're back on the track.

Our JavaFX UI is one of the coolest things on this IT planet.

It's cool because of JavaFX. It's APIs are still not perfect and the overall performance could be better but it has so many awesome things. Two of them are styling via CSS and animations. JavaFX is the official replacement for Swing and it has potential to bring back "write once run anywhere". We don't know if JavaFX will be the holy grail for desktop application development but there's nothing comparable in the Java world.
To be honest, it's not a problem for us because our JVx is (UI) technology independent and if JavaFX won't do it, we'll implement the next UI toolkit for JVx.

... but back to the topic

You should already know that JVx is a Full-stack application framework for building database (ERP) software. It's GUI technology independent and we've different UI implementations. The most important ones are based on Swing and vaadin. We also have native Android and iOS support and our applications run on embedded devices as well. Our applications don't need an application server to work properly because we have a plain socket server as well (IoT ready).

Our preferred Java UI technology was and is still Swing, because it's feature rich and you can build every kind of application without bigger problems. The problem with swing is that it's old and not maintained from Oracle. Sure it will work with future Java releases without bigger problems (hopefully) but you can't use modern development techniques or create fancy and fresh UIs with less effort. A standard Swing application looks boring and cold. Sure, it's possible to pimp a swing application with lots of pictures or nice looking LaFs, but it's not fun.

Swing development is like software development in the stone-age, compared to state-of-the-art web development. If you do web development, you have CSS3 and HTML5 and some nice designed UI frameworks. I won't say that you're faster or that web development is better but it's easier to build nice looking UIs. I'm not a big fan of classical web development because most applications are horrible to maintain, there are soo many different frameworks and you can't be sure that your investment is future-proof because many frameworks don't survive the first year. But everything depends on knowledge and the right framework - for sure.

IMO it's better to use one framework that solves most of application relevant problems - if it exists. If we talk about web applications, I recommend vaadin because it's feature rich, just works, is very polished and is licensed under Apache 2.0. The community is active and great support is available!
Sure, there are some other frameworks like GXT or extJS from Sencha, but the license could be a problem if you build commercial applications. Don't forget RAP, but it's not trivial to start with the whole Eclipse ecosystem.

I'm talking about (enterprise) application development and not about webpage or webservice development. I would recommend pure HTML5 and CSS3 with one or two smaller javascript libs for developing fancy "webpages", or php instead of Java. If Java and "webpages", PrimeFaces is a good decision.

Soo, if Swing is "dead" and web development is hard, what should we use for (enterprise) application development?

If you develop for the desktop, try to start with JavaFX becasue it's maintained and has potential for mobile devices.
If you develop web applications, use vaadin.

(This is my personal opinion, mixed with my technology and project experience)

And why should you use JVx?

JVx bundles all together in one independent framework (it's still small and easy to learn). You'll be independent of the underlying UI technology. Write your application once and start it with different UI technologies or use it on different devices without problems. Your investment is future-proof. JVx is open source and licensed under Apache 2.0. JVx doesn't hide the underlying technology. It's always possible to use features from the technology if you want. If you use a UI without abstraction, you can't switch to another UI easily without rewriting most parts of the UI. If you start with e.g. JavaFX and if Oracle will abandon JavaFX, will you rewrite the application?

You can compare the concept of JVx with SLF4J, but with a different use-case: (enterprise) application development

And what about JavaFX?

I like JavaFX because of, IMO, 5 great things: scene graph, CSS styling, Animations, Web engine and the community. All other things are important and useful but not essential for real-world applications (vs. Swing). It's not possible to compare Swing with JavaFX because JavaFX was written from scratch and Swing was based on AWT. Sure, both toolkits are UI toolkits :) but with different concepts.

JavaFX bridges the gap between desktop and web development. It's still a toolkit for desktop applications but with most advantages of web development. It's possible to create fancy applications without headache. There are cool tools like Scene Builder or ScenicView. IDE support is getting better and developing controls is not too hard.

Sounds too good? JavaFX is on the right track and ready for real-world applications.

That was enough for us to start a JavaFX UI for JVx. It's the only framework which allows switching between Swing, Web, JavaFX or native mobile. Sounds unbelievable? Here's is our first video with our JavaFX implementation. It demonstrates the full power of JVx and JavaFX.

The video starts with our good old Swing UI. The same application will be shown as web application in a Chrome browser. And finally it will run as JavaFX application. You should carefully check the JavaFX application because it has an embedded browser that shows the same application, with a different UI technology - at the same time. Don't miss the animations :)

It's a world premiere!

JVx and JavaFX



We know that the styling is not really cool but we're currently in the development phase and aren't finished... be tolerant :)