JavaFX Real-World Apps: Monastery Disentis

[fusion_builder_container hundred_percent=”yes” overflow=”visible”][fusion_builder_row][fusion_builder_column type=”1_1″ background_position=”left top” background_color=”” border_size=”” border_color=”” border_style=”solid” spacing=”yes” background_image=”” background_repeat=”no-repeat” padding=”” margin_top=”0px” margin_bottom=”0px” class=”” id=”” animation_type=”” animation_speed=”0.3″ animation_direction=”left” hide_on_mobile=”no” center_content=”no” min_height=”none”][fusion_text]

Finally the first “JavaFX Real World Apps” post that actually covers an “app” and not an “application”, meaning the first JavaFX application in this series that was designed for mobile devices and not the desktop. The application is simply called “Monastery Disentis”. It was developed by cnlab in Switzerland. It can be used by visitors of the monastery as a guide. Below you can see a couple of screenshots that were taken on an Android device.

Video: a screencast of the application.[/fusion_text][fusion_text]What is cool about this application is that everybody can try it out be following the links to the app stores, either the Apple App Store for iPhone users or Google Play for Android.

As usual I asked the development team a couple of questions and Daniel Zimmermann was nice enough to answer them below:

General Questions

What is the name of your product / project?

Monastery Disentis

Who are your users / customers?

Monastery of Disentis, Mustér, Switzerland.

What is the purpose of your software? What are its benefits?

Mobile app to guide the user through the monastery church.

Is the application operational? If yes, since when. If not when do you plan to go live?

Yes. It can be installed via the iTunes app store or Google play.

iTunes: https://itunes.apple.com/ch/app/hora-benedicti/id930800749?l=en&mt=8

Google Play: https://play.google.com/store/apps/details?id=ch.cnlab.horabenedicti

Development

How did you get the necessary JavaFX Know-How into your team? (Consultants, Internal / External training courses)?

Internal training.

With which version of JavaFX did you start? 1, 2, 8?

We started with version 8.

When did you start developing the application and how long did it take?

September, 2016, 6 Month with some pauses in between.

How many developers worked on it? In total and on the UI.

2 Developers in total. 1 exclusively on the UI.

How big is the application? Lines of code, Number of classes.

Lines of Code: 11000, No. of Classes: 113.

How big is the JavaFX client? Lines of code, Number of classes.

Lines of Code: 7500, No. of Classes: 51

Why did you choose JavaFX as frontend technology? And very importantly: why did you not choose HTML / Web?

The developer already knew Cordova, but wanted something else. The app‘s scope
seemed small enough to be used for it.

Was it difficult to convince decision makers to agree on JavaFX?

No. Since so we did not need to create two native apps with two developers.

What were the biggest challenges / problems / issues / bugs you faced in the JavaFX part and how did you solve them?

Rendering performance of Text nodes – heavily relied on asynchronous content loading and
lazy content display (in other words: lazily put it onto the Scene Graph).

Which 3rd-party products / frameworks / tools (open source and commercial) did you use and why did you choose them?

JavaFXPorts, Gluon Charm Down, ControlsFX, FontawesomeFX, jackson, commons-codec, Afterburner.fx, ScenicView.

Did you mix JavaFX and Swing code?

No.

Outlook

Would you use JavaFX again for your next project? Please elaborate why or why not.

Yes, but I will think twice for mobile, because the performance is not yet where it needs to
be on all platforms / phone variants.

Which recommendations do you have related to JavaFX for other companies / projects?

Not much, except for: Just give it a try. If you need platform independent Desktop
applications and/or don‘t want to rely on long-term browser support, this is a good and
good-looking alternative.

Which features would you like to see being added to JavaFX?

CSS closer to Web, faster CSS, improved layouting/API, faster text rendering performance.

[/fusion_text][/fusion_builder_column][/fusion_builder_row][/fusion_builder_container]

Advertisement

JavaFX Tip 24: Custom Layouts for Performance and Flexibility

I just finished a two month sprint on advancing CalendarFX and getting it ready for release 8.4.0. One focus of this sprint was on performance. There are many things that can influence performance but when it comes to JavaFX the number of nodes in your scenegraph and CSS styling are top candidates for optimisation. After reviewing the custom controls that ship with CalendarFX I realized that many of them used a lot of nested panes (BorderPane, VBox, HBox, GridPane) in order to achieve a specific layout. Nested panes result in a high node count and complex CSS styling instructions.

One simple example are the views that CalendarFX creates to visualize calendar entries in the DayView control. This control shows the 24 hours of a day vertically and places DayEntryView instances on them. These entry views look like this:

day-entry-view

In the previous releases of CalendarFX the skin of the entry view used a VBox instance to lay out the two labels that show the title of the entry and its start time. That was the only purpose of the VBox. Doesn’t sound like a big issue but when your application starts to show hundreds of those entries then you end up creating hundreds of VBox instances, too.

The way to avoid this is to mange the positioning of these labels yourself and to implement / override the layoutChildren() method of the skin. Not only do we save one node but it also gives us more flexibility. We can now decide to hide or show the labels based on the available space. In the case of the DayEntryView we can decide to hide the start time label if the available height of the view is not big enough to show both labels. This kind of, may I dare to say it, “responsiveness” is not possible when using the out-of-the-box layout panes that are shipping with JavaFX.

The code of the layoutChildren() method of DayEntryViewSkin can be seen below.

[fusion_builder_container hundred_percent=”yes” overflow=”visible”][fusion_builder_row][fusion_builder_column type=”1_1″ background_position=”left top” background_color=”” border_size=”” border_color=”” border_style=”solid” spacing=”yes” background_image=”” background_repeat=”no-repeat” padding=”” margin_top=”0px” margin_bottom=”0px” class=”” id=”” animation_type=”” animation_speed=”0.3″ animation_direction=”left” hide_on_mobile=”no” center_content=”no” min_height=”none”]

    @Override
    protected void layoutChildren(
                               double contentX, 
                               double contentY, 
                               double contentWidth, 
                               double contentHeight) {

        // Title label.
        double titleHeight = titleLabel.prefHeight(contentWidth);

        // It is guaranteed that we have enough height to display 
        // the title (because "computeMinHeight" returns the min
        // height of the title label).

        titleLabel.resizeRelocate(
                snapPosition(contentX), 
                snapPosition(contentY), 
                snapSize(contentWidth), 
                snapSize(titleHeight));

        // Start time label (only show it when there is enough space).

        double timeLabelHeight = 
                           startTimeLabel.prefHeight(contentWidth);

        if (contentHeight - titleHeight > timeLabelHeight) {

            // make sure to set visibility to true again
            startTimeLabel.setVisible(true);

            startTimeLabel.resizeRelocate(
                    snapPosition(contentX), 
                    snapPosition(contentY + titleHeight), 
                    snapSize(contentWidth), 
                    snapSize(timeLabelHeight));

        } else {
            // Not enough space, hide the start time label.
            startTimeLabel.setVisible(false);
        }
    }

The nice thing about the layoutChildren() method is that it tells you exactly which space it is that your children nodes can use. The space is given by the four parameters contentX, contentY, contentWidth, and contentHeight. So there is no need to first lookup things like insets or padding. The “content” rectangle is the space that is available to you.

The second nice thing when writing your own layoutChildren() method is that you can utilize the snapXYZ() methods provided by the SkinBase superclass. These methods ensure that the child nodes will be sized and placed in such a way that they will appear crisp and not blurry. Why is this needed? Because JavaFX uses double precision coordinates to place nodes and unfortunately “int” coordinates are actually located between pixels on your display. So the snapPosition() method might take your x / y coordinate of 100 / 100 and change it to 100.5 / 100.5.

As mentioned before, the DayEntryView is a simple example. Obviously you can also create very complex layouts by overriding the layoutChildren() method. Did I always do this in the current release of CalendarFX? No, I did not. Very often I exchanged all those nested panes with instances of type GridPane, which does give you a lot of layout options but unfortunately no support for responsiveness.

Hope this has been helpful for some of you.

Happy coding![/fusion_builder_column][/fusion_builder_row][/fusion_builder_container]

JavaFX Real-World Apps: SkedPal

skedpal logo v152

A new entry in the “Real World Applications” series. This time it is SkedPal, an application for managing a busy person’s life intelligently. I have been consulting the SkedPal team in matters related to JavaFX and also when they made the decision to start using the CalendarFX framework for their calendar requirements. Below you can see a couple of screenshots of this attractive application. If you want to try it out yourself then you can simply register on the SkedPal website and download the desktop client (they also have mobile clients).

Screen Shot 2016-04-01 at 10.17.33

Screen Shot 2016-04-01 at 11.24.25

Screen Shot 2016-04-01 at 11.24.10

I have asked Saied ArBabian, the found of SkedPal to answer a couple of questions related to their product, their development, and (of course) their use of and thoughts about JavaFX.

General Questions

What is the name of your product / project?

SkedPal

Who are your users / customers?

SkedPal is a publicly downloadable application made for busy professionals who need to schedule their work in order to better manage their time.

What is the purpose of your software? What are its benefits?

SkedPal’s key objective is to assist busy professionals to deliver their projects on time by scheduling all their work intelligently. It’s a SOA cloud-based application that includes a Narrow Artificial Intelligence scheduling engine in the cloud with a JavaFX client for the desktop and an iOS companion app.

Is the application operational? If yes, since when. If not when do you plan to go live?

We’re in public Beta since 2014. We’re into our 3rd pivot and getting closer to the sweet spot for our users.

Development

How did you get the necessary JavaFX Know-How into your team? (Consultants, Internal / External training courses)?

The team was familiar with Swing and it didn’t take too long to get on board with JavaFX in order to deliver the first version. The training process was internal.

With which version of JavaFX did you start? 1, 2, 8?

Started with version 2.

When did you start developing the application and how long did it take?

We have released two versions so far, and we’re in the middle of our third version. We started in late 2013, and had our first version released in Oct 2014. The second version was released in Jun 2015.

How many developers worked on it? In total and on the UI.

5 Developers in total. 2 exclusively on the UI.

How big is the application? Lines of code, Number of classes.

Lines of Code: 132,000, No. of Classes: 860

How big is the JavaFX client? Lines of code, Number of classes.

Lines of Code: 76,000, No. of Classes: 548

Why did you choose JavaFX as frontend technology? And very importantly: why did you not choose HTML / Web?

Our team’s experience was primarily in Java so in order to immediately get started to deliver a front-end application, it was a natural decision to go for JavaFX. In hindsight, a stronger developer community as it exists for HTML/Web could have been a huge help.

Was it difficult to convince decision makers to agree on JavaFX?

No, decisions in startups are made faster and easier than in enterprise environments.

What were the biggest challenges / problems / issues / bugs you faced in the JavaFX part and how did you solve them?

The high memory consumption of JavaFX was particularly a trouble area for us. The only way to resolve it was to consider the performance constraints in our next iteration design and limit our design to what works.

Which 3rd-party products / frameworks / tools (open source and commercial) did you use and why did you choose them?

Initially we used the MiG Java Calendar which was based on Swing code, and then we switched to CalendarFX for its better UI design and use of JavaFX instead of Swing. We developed our own MVVM framework to support our Service Oriented Architecture. It turned out to be a huge project of its own, and we might open source it at some point to contribute to the JavaFX developer community.

Did you mix JavaFX and Swing code?

Initially yes when we used MiG Java Calendar.

Outlook

Would you use JavaFX again for your next project? Please elaborate why or why not.
Which recommendations do you have related to JavaFX for other companies / projects?

We have made a significant investment in JavaFX technology both in terms of team’s experience over the years, as well as development of a complex MVVM framework. This is a strong reason to stay with JavaFX. On the other hand, we really envy the strong developer community that exists for the web apps and we can see how fast development can become once you have access to such communities with large portfolio of open source codes.

In addition, we’re facing severe issues when our users do not opt to update their client to the latest version. Distribution of JavaFX applications for Internet users is a lot more challenging than web based applications.

Which features would you like to see being added to JavaFX?

We’d like to see better performance (speed and memory.)

Do you plan to provide a mobile version of your application or a mobile addition?

We already have a native (Objective C) iOS app integrated into our SOA architecture. The mobile app and the JavaFX desktop apps work in tandem very well in our MVVM framework.

JavaFX Missing Features Survey: Performance & Quality

I take it as a good sign that the categories “Performance” and “Quality” have not seen a lot of submissions in the “Missing Features Survey”.

Performance

In the survey the performance of JavaFX was compared with the performance of Swing and people noticed that JavaFX is slower than Swing. I personally have yet to find a use-case where that is true but I do believe that they can be found, however it should be noted that JavaFX also provides a much better coding experience based on a modern API and architecture. JavaFX supports property bindings and CSS styling. These things of course do take their toll on CPU time. Swing was designed for computer hardware that existed 20 years ago. JavaFX is targeting today’s hardware.

Something that I can agree on is that the use of huge quantities of more or less complex controls within a single stage does lead to performance issues. In a test case that was discussed by several JavaFX experts in Germany, Switzerland, and Austria we looked at the performance of JavaFX when displaying several thousand textfields. This does sound silly but there are use-cases out there that need to create this amount of controls. When comparing the time it took JavaFX to display the textfields to the time it took HTML to do the same we could clearly see that HTML can do it almost instantly while JavaFX needed several seconds. The culprit seems to be the code that performs the CSS styling. Somebody should take a closer look at it. This doesn’t have to be an Oracle employee. The code is open source and available to anybody!

Quality

The following items were mentioned related to quality:

  • WebView needs to be kept up-to-date with the current versions of WebKit
  • Image resizing needs to be improved to ensure that lines do not vanish when decreasing image sizes.
  • Better font rendering (all fonts on all devices).
  • Canvas rendering quality needs to be on par with scene graph rendering.

This is it for the topic “performance and quality”. Next blog will be about CSS and FXML.

Happy coding everyone!

New CalendarFX View: MonthGridView!

Me and my team have recently begun work on a new view for CalendarFX with the initial goal to display a whole year in vertical columns. The name of the view is MonthGridView. As usual the goal has changed slightly while coding. The view is now capable of displaying any number of months with extra months added in front or in the back. Now, for example, the developer can choose to display six months (a semester) with one month “padding” in front and one month in the back.

The following screenshot shows an entire year with no padding.

Screen Shot 2016-04-06 at 09.57.19

In planning and scheduling applications it is often the case that the person using the software wants to quickly compare the same weekdays with each other (e.g. “see resource utilisation on Mondays”). To make this easier the new view also supports a layout option where the same weekdays are aligned. It looks like this:

Screen Shot 2016-04-06 at 10.02.44

As mentioned above, the view can display any number of months with any number of “padding” months. The screenshot below shows a six month period with one month padding on each side (the styling of the extra months still needs some work :-))

Screen Shot 2016-04-06 at 10.14.13.png

The screenshots do not show any calendar information, yet. This part is still work in progress.

If you have any suggestions for features that you would like to see in this view then please leave a comment.

 

Shadow Fields vs. Property Accessor Interface

Carl Dea recently followed up on a blog post of mine called Save Memory! Use Shadow Fields for Properties. In his blog he suggested the use of an interface called “Property Accessor” to eliminate the heavy use of boilerplate code that is needed in order to use  shadow fields. Carl also mentioned that he hasn’t tested his approach with a lot of data and that he or some reader might follow up with a performance comparison. So here it comes.

I wrote a small test application that implements the three strategies that Carl mentions in his post:

  1. standard properties that are instantiated at the same time when the class gets instantiated
  2. property accessor interface as proposed by Carl
  3. shadow fields as proposed in my recent blog post

The code can be found on GitHub. (when you run it please make sure to set the initial and the maximum heap size to 2048 MB -ms2048m -mx2048m, otherwise the memory allocations will mess up the results).

The application allows the user to execute these strategies either with or without asking for the properties. It measures the time spent and the memory used. It should be noted that the measurements are not scientific as I used System.currentTimeInMillis() and Runtime.gc(). When run several times I would still argue that the qualitative value of these tests are acceptable.

The first screenshot below shows the numbers you get when you create between 1,000 and 2,000,000 instances of the Employee class that Carl used for his blog. The tests do not ask for the properties that are available on Employee (name, powers, supervisor, minions):

A1

As you can see the “shadow field” strategy is the fastest and also uses the least amount of memory. This makes sense as the “standard properties” strategy always creates those fat property objects and the “property accessor interface” internally manages a hash map for each model object. Only the “shadow field” strategy works with a minimal amount of data structures. In the case of the selected test it saves a total of 230 MB. If you now imagine that typical applications have many model classes and many of those much more complex than the Employee test class then you can imagine how much memory you can save.

The next screenshot shows the measurements taken when also accessing all four properties and observables inside the Employee class.

A2.png

Now the “standard properties” strategy is the fastest and also the one that uses the least amount of memory. Once again, this makes sense, as this strategy now implements the perfect approach for the given use case. However, the “shadow field” strategy comes in at a very close 2nd place.

Conclusion

The “Property Accessor Interface” strategy is successful at reducing  the noise created by all the boilerplate code needed for shadow fields but it comes at a price that I believe is too high to pay for any application that creates more than just a few model objects.

 

 

P.S.: it should be noted that the comparison is even more in favour of the “shadow fields” strategy when the initial heap size of the JVM is left at its default setting. In this case the test app has to keep asking for more heap space which is quite an expensive operation.

JavaFX Tip 23: Save Memory! Shadow Fields for Properties.

Properties and property bindings introduced in Java 8 are extremely useful programming concepts. They are especially useful when you are developing user interfaces. In fact they are so useful that developers have fallen victim to the idea that everything should be a property instead of a primitive. Unfortunately they easily forget that properties such as SimpleLongProperty are much bigger objects than standard types such as Long. And of course they are much bigger than primitive data types such as long.

In one of my current projects pretty much every model object used by the client is composed of properties. For many of these model objects it is the right approach because they will be edited / modified via JavaFX controls. But there are also many model objects that are not edited. They exist to support the rendering of schedules in the FlexGanttFX control. These objects do not need to be observed, hence they do not need to provide properties … but they do and they waste a lot of memory because they do.

One way to fix this would be to refactor the model classes and to get rid of all properties, but then again we might want to use these objects in a future release in a different context and then we might need properties because we want to edit them directly. What to do?

Shadow Fields

The solution to this problem is something I recently saw Gerrit Grunwald do in the code of his Medusa project and a pattern that was described by Mr. Properties himself Michael Heinrichs.  The pattern makes use of a “shadow field” that is of the same type as the wrapped object inside the property. When using this pattern a property will only be created when it is really needed (“when somebody asks for it”).

Example

In this example we want to manage an attribute called “title”. We need a setter, a getter, and the property accessor.

private String _title = "Untitled"; // shadow field

private StringProperty title;

public final String getTitle() {
    return title == null ? _title : title.get();
}

public final void setTitle(String newTitle) {
    if (title == null) {
        _title = newTitle;
    } else {
        title.set(newTitle);
    }
}

public final StringProperty titleProperty() {
    if (title == null) {
        /// !!!! pass shadow field to constructor
        title = new SimpleStringProperty(this, "title", _title);  
    }

    return title;
}

By using this pattern I was able to bring down the memory footprint from 310 MB to 250 MB for a specific use case in my project. The saved memory is ten times the total memory my computer had when I was a student. Just think about that!

Never too old to learn!

Yesterday (March 16th) I celebrated my 47th birthday. I am now packing a solid 20 years of work experience and a masters degree in computer science. Still I managed to screw up bad.

A potential customer of mine, who is currently evaluating FlexGanttFX for their application, contacted me and argued that the initial model creation takes too long. 22 seconds to be precise. I asked them to send me a standalone demo and when I ran it I could confirm that it takes a long time to create the model. After further investigation I realized that they were creating over 5 million objects (activities that will be placed on the timeline). All of these objects are then inserted into a balanced binary interval tree. When I saw that I basically told them to stop evaluating FlexGanttFX because it will not be able to handle these many objects and that object creation and the tree modifications do take their time. So the basic message I sent was “Go somewhere else. Fu.. off!”.

However, they also included a snapshot of the profiler they used and I could see that most of the time was spent inside the constructor of the base model class “ActivityBase” and not inside the tree modifications (which I found surprising). After some more research I realized that it was primarily the creation of the activity ID, which is of type String and uses UUID.randomUUID(). So I replaced this logic with a simple counter of type Long. After this change the total time went from 22 seconds to 8. Nice! But it got even better.

To be on the safe side I made sure that the start and end times of my activities are initialized with Instant.now(). However, there was no need for that as those times are usually passed to the activity in the constructor or after creation by calling setStart/EndTime(). After this change the total loading time went down to 7 seconds.

Since the problem at hand was to create a lot of objects very fast I decided to change the initial heap size allocated to the program to 2 Gigabytes. This brought down the loading time to 2 seconds.

From 22 seconds to 2 after 10 minutes of work, not bad! However, quite embarrassing considering the initial “Fu.. off!” 🙂

 

JavaFX Missing Features Survey: Table View

The TableView (and TreeTableView) of JavaFX has won the prize for being the control that was mentioned the most in my recent “JavaFX Missing Features” survey and also in many follow-up discussions (including and especially the guys in our Zurich JavaFX Meetup group). I guess one of the reasons is the simple fact that almost every application needs a table view.

The two most requested features / improvements for the TableView were freezing rows / columns and better editing support.

Freezing Rows / Columns

  • Freeze / lock rows – the ability to have one or more rows to stay at the top or bottom of the table view. Often this feature is needed when trying to display the sum of the values in the columns.
  • Freeze / lock columns – the ability to have one or more columns stay on the left or right-hand side of the table view. Again, to show the sum of the values in the row or to display some kind of header for the row. In the case of my FlexGanttFX framework I like to have a column on the left-hand side to show the row number (yes, like in Excel).

I believe that freezing columns / rows was a feature that was planned for the TableView but that did not make it into the final release because of time and resource constraints. If I remember correctly then there is actually some left-over code / comments in the TableView code base that was intended for this purpose.

Editing Support

  • Ability to edit cell values by simply starting to type the new value – currently the user has to double click a cell first.
  • Fluent keyboard navigation to navigate from one cell to another via TAB, SHIFT_TAB, ENTER, arrow keys.
  • Cell validation when editing a value. The user should not be able to leave the cell without either entering a valid value or cancelling the edit.

The current editing support is probably the one thing that annoys developers the most when using the TableView as they know that their users expect more. I have already worked on two projects myself where we had to hack the TableView so that it would let the user edit values directly.

Miscellaneous

Other features that were requested included:

  • Cell / row spanning – the ability to have a cell go across multiple rows and or columns.
  • Filter UI – table views often let the user select one or more filters per column. The collection of all filters then determines the visible rows. In JavaFX this can be easily done in the model (via SortedList and FilteredList) but developers wished there were built-in controls directly inside the TableView (inside the headers).
  • Automatic column sizing – a way to adjust the width of a column to its content, to ensure readability of all values. This feature is actually implemented inside the TableView codebase. It is used to resize the column when the user double clicks on the edges of the column headers. However, the code for this is not public. I have recently posted an article showing how to do it.

I think that all of the above features are valid things to expect from a good table control but I am pretty sure that we will not see any progress in this area from the JavaFX team itself. I believe that from Oracle’s point of view the current table implementation is considered “good enough”, so I assume that it will be up to a third-party to come up with a good alternative, either open-source or commercial. I have brainstormed a lot about how to implement my own table view control but have reached the conclusion that this is too big to be a simple side-project. This is bad, but it also means that there is a potential for somebody else to create a commercial product and to actually make some money with it. Because like I said in the beginning: almost all applications need a table view.

The next “Missing Features” blog will be about performance and quality.

Stay tuned!

P.S.: for some of the features above you might want to try out the SpreadsheetView in the ControlsFX project.