Operativer und experimenteller Einsatz von JavaFX in der Energiewirtschaft

Frischer Wind durch Enterprise JavaFX

Andreas Liebelt

@shutterstock/beatpavel

In manchen Bereichen der Energiewende tritt aktuell eine Konsolidierung ein, doch bei Aus- und Umbau des Energiesystems sind nach wie vor große Fortschritte festzustellen[1]. Ein Innovationsschwerpunkt liegt inzwischen jedoch auf dem effektiveren und effizienteren Einsatz der schon weit über eine Millionen [2] Wind-, PV- und Biomassekraftwerke, die bereits gebaut wurden. Hierfür sind frische, neue und innovative Lösungen gefragt, und das in einer Branche, die sich eher an etablierten und erprobten Technologien orientieren muss. JavaFX kann hier als Brückenschlag fungieren. Doch ist man tatsächlich bereits in der Lage, mit JavaFX innovative Softwareprodukte zu erstellen, welche die notwendige Verlässlichkeit bieten? Eine Wasserstandsmeldung und ein Erfahrungsbericht aus der angewandten Forschung.

Seit meinem letzten Artikel im Java Magazin zum Thema JavaFX sind inzwischen gut anderthalb Jahre vergangen, in denen sich das UI-Framework weiterentwickeln konnte. Damals war JavaFX gerade in Version 8 erschienen, inzwischen wurden diverse Updates veröffentlicht und es liegt aktuell (während ich diesen Artikel schreibe) in Version 8u60 vor. JavaFX ist in dieser Zeit ein großes Stück vorangekommen, genauso wie die vielen Bibliotheken, die auf JavaFX basieren. Insbesondere ControlsFX sei hier erwähnt, dessen Layout-Container und Controls aus unserer Sicht eine fast unverzichtbare Ergänzung zu JavaFX sind.

Abb. 1 : Kraftwerks-Cluster-Ansicht der Leitwarte des virtuellen Kombikraftwerks IWES.vpp des Fraunhofer IWES

Abb. 1 : Kraftwerks-Cluster-Ansicht der Leitwarte des virtuellen Kombikraftwerks IWES.vpp des Fraunhofer IWES

Doch auch unsere Software hat sich stark weiterentwickelt. Sie hat an vielen Stellen von der Entwicklung bei JavaFX profitiert, einzelne Unzulänglichkeiten offenbart und ist manchmal auf echte Hürden gestoßen. Daher stellt sich die Frage, ob und wie gut sich JavaFX aktuell für den Einsatz in Unternehmensanwendungen eignet. Ich möchte dies aus der Sicht unserer Software „Virtuelles Kombikraftwerk“ IWES.vpp (Abb. 1) darstellen, aus unserer Erfahrung den ein oder anderen hilfreichen Tipp geben und auch vor Fallstricken warnen.

Was sind virtuelle Kombikraftwerke?

Energieerzeuger auf Basis erneuerbarer Quellen haben in der Regel kleine Erzeugungsleistungen gegenüber den bestehenden Großkraftwerken – und fluktuieren jeder für sich. Die Vorteile von virtuellen Kombikraftwerken (Abb. 2) liegen zum einen darin, dass die vielen Kleinerzeuger durch die virtuelle Verschaltung eine große Gesamterzeugungsleistung erreichen können. Zum anderen entsteht durch Verwendung unterschiedlicher Anlagentypen (Wind, Solar usw.), die zusätzlich an verschiedenen Orten platziert sind, häufig eine Art passive Erzeugungskurvenglättung (Fluktuationen gleichen sich gegenseitig aus). Dank des Energiemanagements eines virtuellen Kombikraftwerks kann außerdem durch Leistungsminderung oder -erhöhung von Anlagen sowie das Puffern und Abrufen von Energie in bzw. aus Speichern eine aktive Glättung der Erzeugungskurve realisiert werden. Im besten Fall kann durch das Energiemanagement die Erzeugung so gesteuert werden, dass sie eine geforderte Verbrauchskurve exakt erfüllt. Virtuelle Kombikraftwerke werden daher häufig als das zentrale Werkzeug für die Energiewende angesehen.

Abb. 2 : Komponentendiagramm des virtuellen Kombikraftwerks

Abb. 2 : Komponentendiagramm des virtuellen Kombikraftwerks

Die Steuerung eines virtuellen Kombikraftwerks erfolgt genau wie bei einem konventionellen Kraftwerk mithilfe einer Leitwarte. In Leitwarten der konventionellen Variante befindet sich häufig eine Vielzahl von analogen Mess- und Schaltgeräten, wohingegen Leitwarten virtueller Kombikraftwerke vollständig darauf verzichten und ausschließlich Computer und Bildschirme benötigen. Am Zweck der Leitwarte hat sich aber nichts geändert: Das Kraftwerk soll sich im Rahmen vorgegebener Parameter verhalten. Diese Parameter ergeben sich je nach Einsatzzweck zum einen aus der gewinnbringenden Vermarktung an der Strombörse (im Fall von Stromhändlern), zum anderen aus der Gewährleistung eines stabilen Netzbetriebs (im Fall von Netzbetreibern). Die Aufgabe der Leitwarte ist es, dem Bediener die richtigen und wichtigen Informationen anzuzeigen, auf deren Basis er eine Entscheidung für einen Eingriff in den Betrieb des virtuellen Kombikraftwerks treffen kann. Dieser Eingriff muss dann ebenfalls über die Leitwarte geschehen, wobei sicherzustellen ist, dass Eingriffe die gewünschten Auswirkungen haben und Fehleingaben möglichst verhindert werden.

Lesen Sie auch: JavaFX-Standortbestimmung: “Mit Swing gewinnt man heute bei neuen Projekten keine Blumentöpfe mehr”

Bei der Konzeption einer Leitwartensoftware muss eine besondere Anforderung berücksichtigt werden: die Dauerbetriebsstabilität. Es wird von einer Software, die im Leitwartenkontext eingesetzt wird, erwartet, dass sie einen fehlerfreien 24/7-Betrieb gewährleisten kann. Auch nach Wochen, Monaten und sogar Jahren muss die Benutzeroberfläche flüssig und fehlerfrei funktionieren. Selbst wenn Fehler (z. B. unerwartete Exceptions) auftreten, was naturgemäß nicht immer vollständig zu verhindern ist, dürfen diese den ordnungsgemäßen Betrieb der Leitwarte nicht beeinträchtigen. Um auf diese möglichen Fehler reagieren zu können, sind besondere architekturale und algorithmische Sicherungsmaßnahmen zu ergreifen (siehe „Probleme vermeiden“). Da dieses Thema sehr umfangreich ist, kann hier nur in Ansätzen darauf eingegangen werden.

Softwarearchitektur allgemein

Für die Realisierung des Leitsystems für unser virtuelles Kombikraftwerk IWES.vpp setzen wir eine Dreischichtenarchitektur ein, wobei der Client als Rich Client auf Basis von JavaFX 8 konzipiert und die Leitwarte des virtuellen Kombikraftwerks ist. Der Client kommuniziert mit dem Server über eine REST-konforme Schnittstelle, wobei als Austauschdatenmodell ausschließlich verschiedene Profile von IEC CIM 61970, 61968 sowie 62325 verwendet werden. Das Common Information Model (CIM) der International Electrotechnical Commission (IEC) ist ein Datenmodell, das von der Energiewirtschaft für die Modellierung von Energiesystemen entwickelt wird. Der Server verarbeitet sämtliche Eingaben, die mithilfe der Leitwarte getätigt werden und er-greift entsprechende Maßnahmen (z. B. die Drosselung einer Biogasanlage).

Insbesondere die Suche nach einer geeigneten Architektur für unsere Leitwartenbenutzeroberfläche war ein zeitintensiver Prozess, bei dem wir eine optimale Lösung für unsere anspruchsvollen Herausforderungen finden wollten. Um die Wartbarkeit, Performance und Stabilität zu erhöhen und das gemeinsame Entwickeln der Benutzeroberfläche zu erleichtern, entwickelten wir verschiedene Lösungsansätze. Die entscheidenden Anregungen erhielten wir schließlich durch afterburner.fx und die Videos von Adam Bien zu JavaFX. Der daraus entwickelte ganz neue Architekturentwurf auf Basis des MVP-Patterns erfüllt unsere Anforde-rungen auf einem sehr hohen Niveau.

Die UI-Architektur im Detail

Im Kern besteht die Architektur der Leitwarte (Abb. 3) aus streng voneinander getrennten, grafischen Modulen auf Basis des afterburner.fx-Frameworks. Die grafischen Module werden erst bei Bedarf zur Laufzeit erzeugt und zusammengebaut. Jedes grafische Modul basiert auf dem Model-View-Presenter-(MVP-)„Passive View“-Entwurfsmuster und besteht aus mindestens fünf Teilen. Ein Teil ist die Ansicht (View), die sich aus der Kombination eines CSS Stylesheets, einer FXML-Datei sowie dem ResourceBundle mit der aktuell gewählten Sprache ergibt sowie dem Präsentator (Presenter), der ebenfalls Zugriff auf das ResourceBundle hat und Repositories (DDD: Domain-driven Design) nutzt, um Zugriff auf das Datenmodell zu erhalten. Das gesamte grafische Modul wird auf Basis einer Dateinamenskonvention (CoC: Convention over Configuration) durch afterburner.fx zusammengebaut. Optional kann jedes grafische Modul weitere Ressourcen enthalten (z. B. Bilder, spezielle Helper und Arbeits-klassen usw.).

Nahezu durchgängig wird auf gemeinsam genutzte Ressourcen wie etwa Bilder, CSS oder ResourceBundles verzichtet. Das hat zwar gelegentlich die Duplizierung von Ressourcen zur Folge, jedoch ist jedes grafische Modul in der Regel vollständig durch alle Ressourcen in seinem Package definiert. Ungewollte oder unvorhergesehene Wechselwirkungen zwischen den Modulen oder durch Änderung gemeinsamer Ressourcen sind auf diese Art praktisch ausgeschlossen. Dadurch wird die parallele Entwicklung an einer komplexen Benutzeroberfläche signifikant erleichtert. Wo es sinnvoll ist, wird von diesem Paradigma abgewichen. Beispielsweise werden für grafische Komponenten, die immer gleich aussehen sollen, gemeinsame CSS-Stylesheets verwendet (z. B. Button, ComboBox, CheckBox usw.). Dies ist mit 8u20 möglich geworden, da seit dieser Version der @Import-Verweis in Stylesheets verarbeitet wird. Natürlich lagern wir gemeinsamen Code von Presentern in abstrakte Implementierungen aus. Textbausteine, deren Übersetzungen in jedem Kontext gleich sind (z. B. Ok, Abbrechen, Bitte auswählen… usw.), werden mittels TranslationRepo (siehe unten: Repositories) zur Verfügung gestellt.

Abb. 3 : Softwarearchitektur der Leitwarte des virtuellen Kombikraftwerks

Abb. 3 : Softwarearchitektur der Leitwarte des virtuellen Kombikraftwerks

Die innere Funktionsweise eines grafischen Moduls stellt sich wie folgt dar: Ein Interessent (die Applikation oder ein anderes grafisches Modul) holt sich ein grafisches Modul über die getView()-Methode der View, die von deren Elternklasse FXMLView geerbt wird (Teil des afterburner.fx-Frameworks). Mit dem grafischen Modul interagiert der Interessent ausschließlich über das API des Presenters. Dies wird auch mittels Steuerungsumkehr (IoC: Inversion of Control) durch die View (JavaFX) aufgerufen. Der Presenter interagiert mit der View durch View-Objekte (z. B. ComboBox, ListView usw.), die durch JavaFX auf Basis der @FXML-Annotation und fx:id-Variablennamenzuordnung in den Presenter injiziert werden (DI: Dependency Injection).

Der Datenaustausch der grafischen Module erfolgt üblicherweise über Repositories, für deren grundsätzliches Prinzip wir uns von den DataProvidern aus DataFX haben inspirieren lassen, aber auch über das API der Presenter. Listing 1 zeigt ein Beispiel eines Presenters eines grafischen Moduls zur Anzeige der Kraftwerke mit der Möglichkeit der Auswahl eines Kraftwerks mittels Repository oder Setter. Das PowerPlantRepo wird durch afterburner.fx als Singleton injiziert. Die Repositories greifen ihrerseits wiederum auf verschiedene Datenquellen zu. Dies können beispielsweise eine lokale Datei oder die REST-konforme Schnittstelle sein.

Der Energiemanagementserver basiert seit Herbst 2014 ebenfalls auf JDK 8, da wichtige von uns genutzte Frameworks inzwischen kompatibel mit JDK 8 gemacht wurden (z. B. Spring und Apache Camel). Um möglichst hohe Kompatibilität mit unserem breiten (teilweise sehr langlebigen) Softwarelösungsportfolio zu garantieren, basieren unsere Datenzugriffsobjekte (DAO: Data Access Object) für die Leitwarte ausschließlich auf Mechanismen, die in JDK 6 verfügbar sind. Das macht sie in allen unseren Softwarelösungen nutzbar, auch z. B. in deren Integrationstests. Die Datenzugriffsobjekte sind JDK 6 Observables, welche die aus JavaFX Concurrency bekannten Attribute (z. B. Nachricht, Fortschritt usw.) veröffentlichen. Um dies aus JavaFX heraus komfortabel und asynchron nutzen zu können, verwenden wir die Datenzugriffsobjekte mit JavaFX Service und Task, wobei unsere Taskimplementierung als Observer arbeitet und die Observable-Attribute der Datenzugriffsobjekte in die JavaFX Properties von Task übersetzt.

public class PowerPlantsPresenter implements Initializable {

  // JavaFX-controls (injected by JavaFX)
  @FXML ListView listViewPowerPlants;
  @FXML Label labelSelectedPowerPlant;

  // Repositories (injected by afterburner.fx)
  @Inject PowerPlantsRepo powerPlantsRepo; 

  @Override
  public void initialize(URL location, ResourceBundle resources) {
    listViewPowerPlants.setItems(powerPlantsRepo.getData());
    powerPlantsRepo.selectedElement().addListener((powerPlantProperty, oldPowerPlant, newPowerPlant) -> {
        setSelectedPowerPlant(newPowerPlant));
    }
  }

  public void setSelectedPowerPlant(PowerPlant powerPlant) {
    labelSelectedPowerPlant.setText(powerPlant.getName());
  }
}

Mechanismen optimieren

Je umfangreicher eine Anwendung wird, desto essenzieller wird es, den JavaFX Application Thread (FX-Thread) zu entlasten, seltener oder möglichst kurz zu verwenden. Leichte Bedienungsverzögerungen, unschöne „Ruckler“ oder sogar zeitweise Stillstände der Benutzeroberfläche treten sonst mit Sicherheit ein. Nachfolgend werden nun ausgewählte Möglichkeiten vorgestellt, die sich für unsere Einsatzzwecke als sehr vorteilhaft herausgestellt haben.

Parallelisierung: Eine gute und einfache Möglichkeit ist die Parallelisierung von Listenzugriffen durch die Streams aus Java 8, wodurch die Operationen unter geeigneten Umständen [3] insgesamt schneller durchgeführt werden können. Der FX-Thread wird hierdurch kürzer blockiert (auf Kosten einer kurzzeitig erhöhten CPU-Last). Eine weitere Möglichkeit ist die Abarbeitung von aufwändigeren Codeabschnitten in zusätzlichen Threads (z. B. JavaFX Service und Task). Der FX-Thread wird hierdurch entlastet. Das ist jedoch nur sinnvoll bzw. möglich, wenn innerhalb des zusätzlichen Threads keine Änderungen am Scenegraph vorgenommen werden, was die Einsatzmöglichkeiten einschränkt. Eine dritte Möglichkeit ist das asynchrone Laden von grafischen Modulen, was seit afterburner.fx 1.6.0 möglich ist. Auch hierdurch wird der FX-Thread entlastet.

Reaktivität: Eine weitere Möglichkeit zur Verbesserung der Performance ist das „gezielte Nichtausführen“ von Code. Zum einen können Hintergrundprozesse deaktiviert werden, die keinen Einfluss auf die sichtbaren Benutzeroberflächeninhalte haben. Hierfür bietet JavaFX leider keine eigene Möglichkeit. Die Sichtbarkeitsdetektion muss selbst implementiert werden. Zum anderen kann man für bestimmte Mechanismen definieren, mit welcher maximalen Wiederholungsrate sie ausgeführt werden sollen. Beispielsweise soll ein Wert höchstens alle fünf Sekunden neu berechnet werden, auch wenn sich die Eingangswerte im Millisekundenbereich aktualisieren. ReactFX bietet hierfür ein geeignetes API.

Probleme vermeiden

Es gibt Einschränkungen in JavaFX, die man kennen sollte, um ein ungewolltes Applikationsverhalten zu vermeiden. Im Fall von z. B. Lambdaausdrücken sind sie designbedingt, in anderen Fällen auf ungelöste Probleme in JavaFX zurückzuführen. Die im Folgenden ausgewählten Fälle waren für unsere Leitwarte besonders wichtig, da sie den ordnungsgemäßen 24/7-Betrieb beeinträchtigen bzw. verhindern können.

Die Lambdaausdrücke verkürzen und vereinfachen den Code zwar deutlich, es gibt jedoch eine Sache, auf die man achten sollte: Verwendet man sie als Ersatz für Invalidation Listener, Change Listener oder ähnliches, um auf die Änderung von Observables zu reagieren, dann lässt sich dies nicht mehr rückgängig machen. Das liegt an der Arbeitsweise der Lambdaausdrücke selbst: Es liegt zur Kompilierungszeit keine Objektreferenz auf den Listener vor, den man von dem Observable deregistrieren könnte. Eine Instanz des jeweiligen Listener-Interfaces wird erst zur Laufzeit um den Code im Lambdaausdruck herumgewebt. Bei lambdabasierten Listenern handelt es sich also immer um unendliche Listener. Sollen Listener zur Laufzeit ihre Arbeit irgendwann beenden, dann müssen sie wie zuvor als referenzierbares Objekt angelegt werden, um sie später explizit deregistrieren zu können.

Ein wichtiger Aspekt für die Stabilität einer Applikation ist der Umgang mit RuntimeExceptions. JavaFX löst dies größtenteils sehr gut selbst. Es gibt aktuell jedoch Sonderfälle, bei denen man selbst aktiv werden muss, um ein Fehlverhalten, ein Hängen oder sogar einen Absturz der Applikation zu verhindern. Die Exception-Behandlung funktioniert aktuell nicht korrekt bei RuntimeExceptions in den Methoden setCellFactory (TableView, ListView und ComboBox) und setCellValueFactory (Table-View). Tritt eine solche auf, dann stellen fast sämtliche Controls ihre Arbeit fast vollständig ein. Dieses Problem soll voraussichtlich erst mit JavaFX 9 gelöst sein (siehe JDK-8090078 und JDK-8087792). Aktuell empfiehlt sich noch die Verwendung eines Sicherheitspatterns zur Verhinderung von Problemen dieser Art (Listing 2).

listView.setCellFactory(listView -> {
  return new ListCell() {
    @Override
    protected void updateItem(String item, boolean empty) {
      // Safety Pattern (try-catch-Throwable)
      try {
        // Your Code:
        // Update Item
      } catch (Throwable t) {
        // React on Exception
      }
    }
  };
});

tableColumn.setCellValueFactory(value -> {
  // Safety Pattern (try-catch-Throwable)
  try {
    // Your Code:
    // Return Observable Value
  } catch (Throwable t) {
    // React on Exception
  }
});

Frontend-Tests

Das Testen von Benutzeroberflächen ist eine Herausforderung für sich. Im besten Fall erfolgt dies natürlich automatisiert und mit hoher Testabdeckung. Durch das Fehlen geeigneter Frameworks beschränkten wir uns lange Zeit auf das manuelle Testen der Leitwarte im Betrieb. Im Rahmen von Forschungsprojekten ist dieser Ansatz noch praktikabel. Doch der zunehmende Funktionsumfang und der produktive Einsatz der Leitwarte machen automatisierte Tests inzwischen unabdingbar.

In einem ersten Schritt führten wir visuelle ausführbare Tests ein: Es wurden Testfälle für grafische Komponenten aufgestellt, von denen sich jeder als eigenständige Applikation ausführen lässt. Die benötigten Daten werden über Repositories bereitgestellt, die für die verschiedenen Testfälle mit dem Mockito-Framework vorbereitet und mithilfe von afterburner.fx in das zu testende grafische Modul injiziert werden. Es lag nun am Entwickler, den Testfall anhand einer Sichtkontrolle der geöffneten Applikation zu bewerten. Mit zunehmender Anzahl unterschiedlicher Tests stößt diese Vorgehensweise jedoch schnell an seine Grenzen.

Glücklicherweise wurde 2013 eine Version von TestFX veröffentlich, die sich zum ersten Mal hervorragend in unser Testökosystem aus Eclipse, JUnit und Jenkins integriert. Das Ausführen grafischer Unit Tests ist nun direkt aus der IDE möglich und wird automatisch bei jedem Subversion Commit durch Jenkins ausgelöst. Für die Tests nutzen wir die Root Nodes der oben beschriebenen manuellen Tests. Wir erweiterten die Klasse GuiTest aus TestFX jedoch durch eine eigene Klasse, die einen Screenshotvergleich ermöglicht: Hierfür fotografieren wir den Bildschirm auf Basis der Koordinaten der durch TestFX erzeugten Stage und vergleichen das Ergebnis mit einem hinterlegten Referenzbild. Für den Vergleich lässt sich ein Grenzwert der erlaubten Abweichung einstellen.

Lesen Sie auch: Produktives Hacking mit JavaFX 8

Aktuell kommt es beim Ausführen der Tests mit Jenkins zu Engpässen in der Infrastruktur, da für Frontend-Tests ein Rechner (Jenkins-Slave) inklusive angeschlossenem Bildschirm erforderlich ist. Pro Rechner kann nicht mehr als ein Test gleichzeitig ausgeführt werden, da es sonst zwischen den Tests zu Wechselwirkungen von Fensteraussehen, Maus- und Tastatureingaben kommt. Daher können Frontend-Tests auf einem Rechner nur seriell ausgeführt werden. Eine Parallelisierung lässt sich nur über den Zubau von Rechnern inklusive Bildschirmen realisieren, was zusätzlich Kosten verursacht und Platz benötigt. Eine Kapselung der Visualisierung steht mit „Monocle“ bereits in den Startlöchern, aber eine entsprechende Lösung für die Maus- und Tastatur-Interaktion wäre noch zu entwickeln und mit Monocle in einem Testframework (z. B. TestFX) zusammenzubringen.

Frontend-Auslieferung

Alle unsere Produkte, und damit auch die Leitwarte, unterstützen den Build-Prozess von Maven in der Version 3. Im durch die pom.xml konfigurierten Build-Prozess nutzen wir das javafx-maven-Plug-in in Kombination mit Inno Setup, um einen Windows Installer zu erzeugen. Wir liefern fast ausschließlich eigenständige Applikationen (mit enthaltenem JRE) aus, damit unsere Kunden kein Java installieren müssen und wir weniger Freiheitsgrade auf den Kundenrechnern berücksichtigen müssen. Außerdem erscheint es uns sinnvoller, eine Installationsdatei auszuliefern, statt den Kunden durch Java-Web-Start-Dialoge klicken zu lassen.

Ein großes Manko ist aktuell noch, dass man nur für das Betriebssystem einen Installer erzeugen kann, auf dem der Build-Prozess durchgeführt wird (z. B. Windows/siehe JDK-8091902). Außerdem lässt sich durch ein JDK jeweils nur diejenige Bit-Variante des Installers bauen, die der Bit-Architektur des JDK entspricht (z. B. nur 32 Bit Installer mit 32 Bit JDK/siehe JDK-8091056). Führt man das Maven-Release mit einem 32 Bit JDK aus, dann lässt sich nur ein 32 Bit Installer erzeugen, und führt man es mit einem 64 Bit JDK aus, dann nur ein 64 Bit Installer. Möchte man Installer für beide Bit-Varianten ausliefern, dann muss man aktuell das Release einmal mit dem einen JDK und danach mit dem anderen durchführen und erhält dementsprechend zwei Installer mit unterschiedlicher Versionsnummer.

JavaFX: Verlässlichkeit und andere Problemchen

Doch wie steht es ganz allgemein um die Verlässlichkeit von JavaFX? Ich möchte dies anhand von ein paar Beispielen illustrieren:

Es ist uns leider nicht möglich, von 8u51 zu 8u60 zu migrieren, was erneut mit einer zuvor funktionsfähigen Komponente zu tun hat, die nach einem Update nicht mehr korrekt funktioniert (Regression). In unserem aktuellen Fall betrifft es die LineChart-Komponente, die für unsere Applikation von entscheidender Bedeutung ist (Abb. 1). Alle Achsen, Linien und Hilfslinien werden seit 8u60 unscharf dargestellt, was dieses Release für uns unbenutzbar macht. Es ist nicht das erste Mal, dass wir ein Update überspringen oder selbst einen Workaround für eine Regression in JavaFX schreiben mussten.

Ein weiterer Kritikpunkt, den ich nicht unerwähnt lassen möchte, ist das stillschweigende Einführen von (durch die OpenJDK-Entwickler) gewollten Änderungen („It’s not a Bug, it’s a Feature“). So wurde zum Beispiel mit 8u20 das Verhalten der Buttons verändert. Wenn man in einem Fenster die Enter-Taste benutzt, wird immer der Default-Button ausgelöst, auch wenn ein anderer Button fokussiert ist. So wird man (zumindest als Windows-Benutzer) beispielsweise von folgendem Verhalten überrascht: Wenn man in einem Bestätigungsdialog mit der Tastatur den ABBRECHEN-Button fokussiert und ENTER drückt, wird trotzdem der OK-Button ausgelöst. Das kann sehr gefährlich sein! Aktuell gibt es keine (einfache) Möglichkeit, das zu umgehen. Mit JDK-8136599 soll eine Möglichkeit gesucht werden, das beschriebene Verhalten anpassbar zu machen. Ausführlichere Release Notes für JavaFX würden an dieser Stelle die Transparenz für die Entwickler auf sinnvolle Weise erhöhen.

Es kommt außerdem immer wieder vor, dass man vermeintlich simple Dinge mit JavaFX-Komponenten umsetzen möchte und dabei merkt, dass das Vorhaben nur sehr aufwändig umzusetzen ist oder gar nicht. So wollten wir beispielsweise ListViews mit CheckBoxListCells durch die Tastatur bedienbar machen (Pfeiltasten hoch/runter, Leertaste ändert Selektion der gerade fokussierten Zelle): Nahezu 100 ziemlich umständliche Codezeilen mussten wir schreiben, um den ListViews das beizubringen. Wiederum das einfache Aus- und Einblenden einzelner Zeilen und Spalten ist mit der GridPane grundsätzlich unmöglich.

Fazit

Ich wollte die Frage beleuchten, ob es möglich ist, mit JavaFX innovative Softwareprodukte zu erstellen und gleichzeitig die notwenige Verlässlichkeit für Unternehmensanwendungen zu erhalten. Diese Frage würde ich aktuell mit einem einschränkenden JA beantworten. Die erwähnten Schwächen sind häufig nicht so gravierend, dass eine ernsthafte Beeinträchtigung des Entwicklungsprozesses festzustellen wäre. Und wenn man die aktuellen Schwächen kennt, dann kann man sie meist gut umgehen. Wenn man auf einer größeren Zeitachse die Entwicklung ansieht, kann man feststellen, dass gerade im letzten Jahr der Reifegrad deutlich zugenommen hat. Viele Probleme wurden beseitigt und neue Probleme sind immer seltener aufgetreten.

Innovative Software hängt zwar sehr stark von der zugrunde liegenden Idee ab, aber eine hübsche und schnelle Umsetzung durch das verwendete Framework trägt meines Erachtens zu einem großen Teil zum Erfolg bei. JavaFX hat hier einiges zu bieten, auch wenn noch nicht für alle Anforderungen die passenden Layoutcontainer oder Controls verfügbar sind. Die aktuelle JavaFX-Version in Kombination mit den genannten Bibliotheken liefert eine sehr breite Basis an Komponenten, mit deren Hilfe man sehr viele verschiedene Use Cases realisieren kann. Doch wenn man die Technologie sehr stark ausreizen möchte, sollte man nicht davor zurückschrecken, den JDK Issue Tracker zu nutzen. Auch die Unterstützung der einschlägigen Frameworks, wie z. B. ControlsFX, kommt allen und am Ende auch einem selbst zugute. Ich bin äußerst optimistisch, dass das JavaFX-Ökosystem weiter wachsen und reifen wird, um bald uneingeschränkt für Unternehmensanwendungen einsetzbar zu sein.

Verwandte Themen:

Geschrieben von
Andreas Liebelt
Andreas Liebelt
Andreas Liebelt ist Diplom-Ingenieur (FH) und Master of Science. Er arbeitet als Wissenschaftler am Fraunhofer-Institut für Windenergie und Energiesystemtechnik IWES am Institutsteil Energiesystemtechnik in Kassel. Zu seinen Kernaufgaben gehören die Entwicklung von Layout, Design und Architektur energiewirtschaftlicher Benutzeroberächen sowie die Anwendung des IEC-CIM-Datenmodells in operativen virtuellen Kombikraftwerken.
Kommentare

Hinterlasse einen Kommentar

Hinterlasse den ersten Kommentar!

avatar
400
  Subscribe  
Benachrichtige mich zu: