Über unsMediaKontaktImpressum
René Jahn 08. September 2015

Ein GUI für alle Fälle

Die Erstellung von modernen und optisch ansprechenden Anwendungen ist gerade ein heißes Thema. Egal welche Fachzeitschrift oder welches Onlinemagazin gelesen wird, ein Artikel über JavaFX ist immer dabei. Wer Webanwendungen bevorzugt, findet auch ganz bestimmt einen Artikel über Vaadin. Und natürlich gibt es immer wieder Berichte über neue JavaScript-/CSS-Frameworks. Doch bei all den modernen Entwicklungen müssen letztendlich Anwendungen umgesetzt werden, mit denen die Probleme von Endanwendern gelöst werden. Doch kann das mit all den neuen Technologien überhaupt funktionieren? Am Ende des Tages müssen Anwendungen einige Jahre laufen um die Entwicklungskosten einzubringen. Die Umstellung auf eine neue Technologie ist oftmals stellvertretend für eine Neuentwicklung.

Gerade im Java-Umfeld wurden viele Anwendungen basierend auf Swing erstellt. Dabei handelt es sich um ein UI-Toolkit, das ursprünglich von Sun entwickelt wurde. Dieses Toolkit ist nach wie vor weit verbreitet und auch in allen JDKs enthalten. Allerdings wird es nicht mehr weiterentwickelt oder gewartet. Der offizielle Nachfolger ist bereits im aktuellen JDK 8 integriert und trägt den Namen JavaFX. Dabei handelt es sich um eine moderne UI-Technologie mit der unter anderem Transformationen, Animationen, Web Browser, Touch-Eingaben oder ein Media-API ohne nennenswerten Aufwand verwendet werden können. Das ist natürlich nicht alles, denn das Styling einer Anwendung mittels CSS ist ein weiteres Killer-Feature. Im Prinzip ermöglicht JavaFX die Umsetzung von optisch ansprechenden Anwendungen ohne größere Einschränkungen. Mit Standard Swing sind vergleichbare Features nicht denkbar. Natürlich gibt es zusätzliche Bibliotheken für Swing, aber bestimmte Möglichkeiten wie beispielsweise Zooming sind einfach nicht vorgesehen. Es ist auch nicht möglich, eine Swing-Applikation unter iOS oder Android zu starten. Mit JavaFX hingegen ist das machbar.

Aber keine Angst, nur weil JavaFX der neue Platzhirsch ist, bedeutet das nicht, dass Swing aussterben wird. Es wird uns wohl weiterhin im JDK erhalten bleiben und Anwendungen können weiterhin damit laufen. Aber wenn eine Anwendung "modern" sein muss, sollte ernsthaft über eine Migration nachgedacht werden. Es gibt diverse Migrationsmöglichkeiten für Swing zu JavaFX, aber nur die reine Ablöse schafft wirkliche Zufriedenheit [1].

Technologieunabhängige Ablöse

Wenn schon über den Einsatz oder den Wechsel zu JavaFX nachgedacht wird, sollte berücksichtigt werden, dass es sich dabei um eine Technologie für Desktopanwendungen handelt. Die Erstellung von Webanwendungen ist nicht vorgesehen. Auch wenn der eine oder andere Leser die Bck2Brwsr VM [2] kennen mag, so sei zu erwähnen, dass es nicht mehr als ein Test für die Portierung war. Der Projekteinsatz ist aktuell nicht denkbar.

Wie bereits erwähnt wurde, ist es möglich, eine JavaFX-Applikation auch für Android oder iOS bereitzustellen. Durch die Anstrengungen des JavaFXPorts-Projektes [3] wurde dies überhaupt erst möglich. Es handelt sich dabei zwar um kein offiziell von Oracle unterstütztes Projekt, aber es wird von Firmen vorangetrieben, die ein kommerzielles Modell darum aufgebaut haben. Es gibt auch bereits erste JavaFX-Anwendungen in den App-Stores.

Bevor Sie sich von Swing loslösen und auf JavaFX setzen, sollten Sie noch über eine Alternative Bescheid wissen. Denn durch den Wechsel zu JavaFX würden Sie zwar auf eine moderne UI-Technologie setzen, aber Sie sind auch wieder an diese gebunden. Wenn beispielsweise ein Nachfolger für JavaFX das Licht der Welt erblicken würde, hätten Sie die gleichen Probleme wie beim Wechsel von Swing zu JavaFX.

Warum also nicht zu einer Technologie wechseln, die unabhängig vom UI-Toolkit ist? Dieser Vorschlag klingt zugegeben etwas unglaubwürdig, aber es gibt tatsächlich diese Möglichkeit und zwar in Form des Open Source-Frameworks JVx [4].

Das Framework ist ein sogenanntes Full-Stack-Framework für die Anwendungsentwicklung. Vereinfacht gesagt kann mit einem einzigen Framework eine komplette Anwendung vom GUI bis hin zur Persistenz umgesetzt werden. Die Architektur des Frameworks folgt dabei dem Prinzip des Schichtenmodells [5] für die Erstellung von Softwaresystemen. In JVx wurden eine Präsentationsschicht, eine Logikschicht und eine Datenhaltungsschicht umgesetzt. Jede Schicht wurde abstrahiert und kann unabhängig von den anderen Schichten ausgetauscht werden. Dadurch könnte beispielsweise die GUI-Schicht entweder Swing, JavaFx oder eine andere UI-Technologie sein. Dies ist aber noch nichts Besonderes, denn es ist jedem Entwickler klar, dass eine Swing-Anwendung an ein beliebiges Backend gekoppelt werden kann, sei es mit REST Services, via RMI oder Spring. Eine JavaFX-Anwendung könnte ebenfalls auf das gleiche Backend zugreifen und man hätte dann zwei Anwendungen in zwei unterschiedlichen Technologien.

Doch das schafft keine Verbesserung und deswegen geht JVx einen Schritt weiter. Es ermöglicht die Entwicklung einer einzelnen Anwendung, die mit unterschiedlichen Technologien lauffähig ist. Die Anwendung wird ein einziges Mal codiert und mit Swing oder JavaFX gestartet. Im Fachjargon wird üblicherweise der Begriff "Single Sourcing" verwendet.

Das Spezielle am Single Sourcing-Ansatz von JVx ist, dass die tatsächlich eingesetzte Technologie jederzeit direkt verwendet werden kann und nicht vor dem Entwickler versteckt wird. Damit kann sowohl Technologie-unabhängig als auch Technologie-spezifisch entwickelt werden. Der Vorteil an der Technologieunabhängigkeit besteht natürlich darin, dass die Applikation nicht verändert werden muss, um auf eine neue Technologie zu wechseln. Das löst ein entscheidendes Problem. Die neu entwickelten oder migrierten Anwendungen sind sofort zukunftssicher. Anhand einer einfachen "Hello World"-Anwendung wird die besagte Technologieunabhängigkeit demonstriert. Der Source Code in Listing 1 zeigt eine einfache JVx-Anwendung.

public class HelloWorldApplication extends Application
{
    public HelloWorldApplication(UILauncher pLauncher)
    {
        super(pLauncher);
   
        UIBorderLayout bl = new UIBorderLayout();
        bl.setMargins(10, 10, 10, 10);
       
        setLayout(bl);
       
        add(new UILabel("Hello LABEL!"));
        add(new UIButton("Press My BUTTON!"), UIBorderLayout.SOUTH);
    }
}

Die Klasse HelloWorldApplication wird von der Basisklasse Application abgeleitet. Dadurch wird die Klasse als JVx-Anwendung gekennzeichnet. Im Konstruktor wird ein Parameter vom Typ UILauncher an die Application übergeben. Ein Launcher ist die Startklasse einer Anwendung in einer spezifischen Technologie. Vereinfacht gesagt, die Klasse mit der main- Methode. Durch den Konstruktor erhält die Applikation die Möglichkeit, auf die Startklasse zuzugreifen.

Sehen wir uns nun die Anwendung mit unterschiedlichen Technologien an. In Abb.1 kommt die Swing-Variante zum Einsatz und in Abb.2 wird JavaFX verwendet.

Anhand der Abbildungen ist bereits zu erkennen, dass die JavaFX-Variante etwas hervorsticht. Der Fensterinhalt ist zwar ident zu der Swing-Variante, jedoch sind die Fensterrahmen komplett unterschiedlich. Das liegt daran, dass bei JavaFX ein gestyltes Fenster zum Einsatz kommt. Dieses bietet zusätzliche Features wie beispielsweise Zooming. In Abb. 3 wurde der Inhalt des Fensters vergrößert (Zoom-in). Mit den Scroll-Balken kann der Inhalt verschoben werden.

Dieses Feature wäre mit Swing nicht denkbar, vor allem nicht, weil der Button zu jeder Zeit gedrückt werden kann. Es handelt sich dabei nicht um ein statisches Bild, das vergrößert wurde und die Fonts sind ebenfalls nicht verändert worden.

Wie funktioniert das Ganze?

Damit eine Applikation nur einmalig codiert werden muss, um dann in unterschiedlichen GUI-Technologien dargestellt zu werden, bedarf es einer UI-Abstraktion. Genau das übernimmt JVx. Es definiert ein GUI anhand von Java-Interfaces. Das wird vereinfacht mit einem simplen Button im folgenden Listing gezeigt.

public interface IButton extends IComponent                                  
{
    public String getText();
    public void setText(String text);

    public void setImage(IImage image);
    public IImage getImage();
}

Analog zu dem Button gibt es weitere Interfaces für Label, Image, Textfeld, Farbe, Tabelle, Tree usw.

Für jede UI-Plattform muss eine Implementierung dieser Interfaces durchgeführt werden. Im nächsten Listing wurde der Button für Swing implementiert.

public class SwingButton extends SwingComponent<JButton>
                         implements IButton
{
    public SwingButton()
    {
        super(new JButton());
    }    

    public String getText()
    {
       return resource.getText();
    }

    public void setText(String pText)
    {
        resource.setText(pText);
    }

    public IImage getImage()
    {
        return image;
    }
    
    public void setImage(IImage pImage)
    {
        if (pImage == null)
          {
              resource.setIcon(null);
        }
          else
          {
              resource.setIcon((ImageIcon)pImage.getResource());
          }

        image = pImage;
    }
}

Die Implementierung ist nicht sonderlich kompliziert. Es wird ein JButton instanziert und die Interface-Methoden werden an die Ressource – sprich den JButton – weitergeleitet. Zusätzlich zu den Interfaces gibt es plattformunabhängige Hüllenklassen um die GUI-Komponenten einfach anzusprechen, wie z. B. UIButton für den Button. Beim Starten der Anwendung wird durch den Launcher die jeweilige UI-Implementierung instanziiert und durch Verwendung des Factory-Pattern werden zur Laufzeit die richtigen Komponenten erstellt.

Durch UI-Abstraktion können Technologie-spezifische Probleme bereits in der Implementierung gelöst werden und die JVx-Anwendungen bekommen von all diesen Problemen nichts mit. Das Ziel von Technologie-unabhängig ist auch, dass die Anwendungsentwickler soweit als möglich von Technologieproblemen befreit werden. Schließlich macht es mehr Spaß ein Feature zu entwickeln, als nach Lösungen für die Probleme einer Technologie zu suchen.

Was ist der Mehrwert?

Der größte Pluspunkt von Technologieunabhängigkeit ist, dass eine Anwendung nur einmalig codiert werden muss. Egal, welche Technologie letzten Endes eingesetzt wird. Das spart Zeit und ist zukunftssicher.

Grundgedanke von Java: Write once, run anywhere.

Die Komplexität einer Technologie kann vom Entwicklerteam ferngehalten werden und der Fokus liegt auf der Umsetzung von Kundenwünschen. So richtig deutlich wird der Mehrwert aber erst, wenn eine Anwendung ohne Änderungen am Source Code auch als Webanwendung oder als App am Smartphone eingesetzt werden kann. Das deckt sich auch mit dem Grundgedanken von Java "Write once, run anywhere".

Damit das Bild deutlicher wird, verwenden wir eine aussagekräftigere Anwendung als unser "Hello World"-Beispiel. Eine ERP-Anwendung, die auch als Demo für das JVx-Framework zum Einsatz kommt. Der vollständige Source Code ist auf der Projektseite [6] verfügbar. In Abb.4 ist die JavaFX-Variante abgebildet. In Abb.5 läuft das Ganze im Browser mit Vaadin als UI-Technologie und in Abb.6 ist die iOS-Variante zu sehen.

Die Vaadin-Variante verwendet einen speziellen Style, damit die Anwendung nicht nach einer Desktop-Anwendung aussieht. Die Anwendung selbst ist aber Source Code-ident.

Es macht natürlich nicht immer Sinn, die gleichen Bearbeitungsmasken am Desktop, im Browser oder am Smartphone bereitzustellen. Vor allem für geringe Bildschirmgrößen sollten die Masken angepasst werden. In der Praxis kommt es aber häufig vor, dass Eingabeformulare im Browser benötigt werden, eine Desktop-Anwendung als Backend zur Verwaltung der Formulare zum Einsatz kommt und am Smartphone diverse Statistiken bereitgestellt werden. Wenn das alles mit einer einzigen Anwendung und Technologie machbar ist, dann freut das auch das Entwicklungsteam. Vor allem wenn die Anwendung gewartet werden muss.

Fazit

In der GUI-Entwicklung findet schon seit längerem ein Umbruch statt. Es ist daher sehr wichtig, die richtigen Entscheidungen zu treffen um zukunftssicher zu agieren. Gerade bei der Auswahl der Basistechnologie sollte auf Unabhängigkeit geachtet werden. Aber auf keinen Fall auf Flexibilität verzichten. Wer die Ablöse von Swing-Applikationen plant, der sollte gut evaluieren und unbedingt alle Alternativen berücksichtigen. Denn unter Umständen reicht eine reine Desktop-Anwendung nicht mehr aus, um alle Kundenwünsche abzudecken.

Autor

René Jahn

René Jahn ist Mitbegründer der SIB Visions GmbH und Head of Research & Development. Er verfügt über langjährige Erfahrung im Bereich der Framework- und API-Entwicklung. Sein Schwerpunkt liegt auf der Integration von State of the...
>> Weiterlesen
botMessage_toctoc_comments_9210