Viele Desktop-Anwendungen setzen heute auf webbasierte UIs. Dieser Ansatz kombiniert die Flexibilität gängiger Webtechnologien mit der Performance und den Integrationsmöglichkeiten nativer Apps.

Unsere Java-Desktop-App folgt diesem Ansatz. Die Oberfläche basiert auf einer Web-UI, die mit Vue.js und Tailwind CSS umgesetzt ist und auf allen unterstützten Plattformen ein konsistentes, responsives Nutzerverhalten bereitstellt.

Web-UI vs. Native-UI 

Klassische native UI-Toolkits für Desktop-Anwendungen konnten mit modernen Anforderungen lange nicht mithalten. Für ein konsistentes Erscheinungsbild, Animationen, eine korrekte High-DPI-Darstellung oder flexible Theme-Optionen wie in Web-UIs (Light/Dark Mode, Farbvarianten usw.) war meist erheblicher zusätzlicher Aufwand nötig.

Webbasierte UIs profitieren dagegen von einem großen Ökosystem an sofort einsetzbaren Bibliotheken, Komponenten-Frameworks, responsiven Layouts und einer einheitlichen Darstellung über verschiedene Betriebssysteme und Formfaktoren hinweg.

Durch das Einbetten einer Web-UI in eine Desktop-Shell lassen sich moderne, weborientierte Oberflächen mit den Fähigkeiten einer nativen Anwendung kombinieren. Reine Webanwendungen können Desktop-Apps nicht vollständig ersetzen, da ihr Zugriff auf Dateisystem, Betriebssystem-APIs und Offline-Funktionen eingeschränkt ist. Läuft die Web-UI jedoch in einem nativen Wrapper, schließt das diese Lücke und beide Ansätze lassen sich in einer gemeinsamen Architektur verbinden.

Überblick über die Anwendung 

Die Anwendung ist eine plattformübergreifende Java-Desktop-App, die eine moderne Vue.js-Weboberfläche in ein natives Java-Fenster einbettet. Die UI arbeitet mit einem reduzierten Layout und klaren Bedienkonzepten, realisiert mit Shadcn-Komponenten.

Diese Architektur stellt sicher:

  • Eine konsistente Darstellung unter Windows, macOS und Linux.
  • Flüssige Interaktionen und Übergänge, wie man sie aus Webanwendungen kennt.
  • Offline-Verfügbarkeit, da alle benötigten Daten und Assets mitgeliefert werden und die Anwendung ohne Internetverbindung läuft.

Beim Start zeigt die Anwendung ein zentrales Dashboard sowie einen Einstellungen-Dialog, in dem Nutzer Parameter wie UI-Theme, Schriftgröße und Layout-Optionen anpassen können. Alle Einstellungen werden lokal im Dateisystem abgelegt und beim nächsten Start automatisch geladen.

Desktop-Anwendung mit UI in Vue.js

Desktop-Anwendung mit UI in Vue.js.

Der vollständige Quellcode ist auf GitHub verfügbar.

Anwendungsfenster und Webview 

Das Hauptfenster wird über ein JFrame aus Java Swing erstellt, da es fester Bestandteil von Java ist und sich unkompliziert einsetzen lässt. Darin ist eine Chromium-basierte Webview-Komponente von JxBrowser eingebettet. Die Komponente rendert die Vue.js-Oberfläche direkt im Desktopfenster und stellt vollständige moderne Browserfunktionen bereit.

var engine = Engine.newInstance(HARDWARE_ACCELERATED);
var browser = engine.newBrowser();

SwingUtilities.invokeLater(() -> {
    var view = BrowserView.newInstance(browser);
    var frame = new JFrame("Application");
    frame.addWindowListener(new WindowAdapter() {
        @Override
        public void windowClosing(WindowEvent e) {
            engine.close();
        }
    });
    frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
    frame.add(view, BorderLayout.CENTER);
    frame.setSize(1280, 900);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
});

Die Struktur trennt die Verantwortlichkeiten klar: Das Java-Backend übernimmt die zentrale Logik wie Datenlesen, Speichern und Dateioperationen, während das Vue.js-Frontend für Layout und Interaktion zuständig ist.

Laden der Web-UI in der Desktop-Anwendung 

Der Vue.js-Teil der Anwendung ist ein gewöhnliches Webprojekt. Abhängig von der Umgebung lädt die Desktop-App die UI entweder von einem lokalen Dev-Server oder aus eingebetteten statischen Dateien.

Entwicklungsumgebung 

Das Laden der Web-App in der Entwicklungsumgebung ist unkompliziert. Ein lokaler Dev-Server wird gestartet, und die Anwendung lädt die Oberfläche über localhost:

./gradlew desktop-web-app:startDevServer -Pfrontend=vue
if (!AppDetails.isProduction()) {  
   browser.navigation().loadUrl("http://localhost");
} else {
   ...
}

Beim Start der Anwendung navigiert die eingebettete Webview zu dieser lokalen Adresse. Änderungen an Vue-Komponenten oder Styles werden dadurch sofort sichtbar, ohne dass der Java-Teil neu gebaut werden muss.

Produktionsumgebung 

In der Produktion arbeitet die Desktop-Anwendung vollständig offline. Ein lokaler Webserver kam dafür nicht in Frage – er hätte zusätzliche Komplexität und potenzielle Sicherheitsrisiken erzeugt.

Das Ausliefern der UI über einen lokalen oder entfernten Server erhöht das Sicherheitsrisiko; Nutzer könnten die URL der Web-App direkt im Browser öffnen und den Quellcode einsehen, wodurch interne Logik offengelegt würde. Das möchten wir vermeiden – die UI soll ausschließlich innerhalb der Desktop-Anwendung verfügbar sein, und der Quellcode muss im Paket verborgen bleiben.

Um das zu erreichen, werden die Dateien der Web-App in die Ressourcen aufgenommen und über den Klassenpfad bereitgestellt. Dafür kommt die Scheme-Intercepting-API von JxBrowser zum Einsatz, über die die Anwendung eigene Requests abfängt und die eingebetteten Dateien zurückliefert.

Damit der Request-Interceptor die Anfragen auf Webressourcen verarbeiten kann, wird er einem eigenen Protokoll zugeordnet:

var options = EngineOptions.newBuilder(HARDWARE_ACCELERATED)
        .addScheme(Scheme.of("jxb"), new UrlRequestInterceptor());
var engine = Engine.newInstance(options.build());

Die Vue.js-Anwendung wird direkt als Ressourcen in das Java-Paket eingebunden und anschließend über JxBrowser geladen. Dadurch ist der UI-Teil vollständig in sich geschlossen:

  • Alle HTML-, CSS- und JavaScript-Dateien werden direkt aus dem JAR der Anwendung bereitgestellt.
  • Ein externer Server ist nicht erforderlich.
  • Und der Quellcode ist im Browser nicht einsehbar.

Dieser Ansatz führt zu einer schnellen, sicheren und portablen Desktop-Anwendung, die sich unter Windows, macOS und Linux einheitlich verhält.

Kommunikation zwischen Vue.js und Java 

Damit die Anwendungslogik funktioniert, kommuniziert das Vue.js-Frontend mit dem Java-Backend – etwa um auf der Festplatte gespeicherte Einstellungen auszulesen oder zu ändern.

JxBrowser-Bridge zwischen JavaScript und Java 

JxBrowser stellt eine Bridge zwischen JavaScript und Java bereit, über die die Web-UI Java-Methoden direkt aufrufen kann. Das Vue.js-Frontend triggert dabei Backend-Funktionen (z. B. „Theme-Einstellungen speichern“), während die Java-Seite Ereignisse oder aktualisierte Daten zurück an das Frontend sendet.

So werden in JxBrowser die Typen für die Kommunikation zwischen JavaScript und Java deklariert:

@JsAccessible
class PrefsService {
    void setFontSize(int size) {
    
    }
}
declare class PrefsService { 
    setFontSize(size: number): void; 
}

declare const prefService: PrefsService;

prefsService.setFontSize(12);

Protobuf + gRPC 

Wir haben Protocol Buffers (Protobuf) und gRPC integriert, um eine schnellere und typsichere Kommunikationsschicht zwischen Vue.js und Java bereitzustellen.

Mit Protobuf definieren wir Datenstrukturen und Service-APIs zentral und erzeugen daraus automatisch stark typisierten Client- und Servercode für beide Seiten. Die Nachrichten und Services werden in einer .proto-Datei beschrieben, und Protobuf generiert daraus den entsprechenden Java- und TypeScript-Code.

service PrefsService {
  rpc SetFontSize(FontSize) returns (google.protobuf.Empty);
}

enum FontSize {
  SMALL = 0;
  DEFAULT = 1;
  LARGE = 2;
}

gRPC fungiert dabei als Transportschicht – das Java-Backend betreibt einen leichtgewichtigen gRPC-Server, und die Vue.js-App kommuniziert als Client mit ihm, indem sie strukturierte Daten sicher und effizient sendet und empfängt.

Das brachte:

  • Typsicherheit auf beiden Seiten der Anwendung.
  • Autovervollständigung und Fehlerprüfung bereits beim Build.
  • Bessere Erweiterbarkeit, sobald zusätzliche Funktionen oder APIs hinzukommen.

Kommunikationsdiagramm

Kommunikationsdiagramm.

Fazit 

Desktop-Anwendungen mit Web-UIs zu entwickeln, hat sich als ein leistungsfähiger, moderner Ansatz erwiesen. Er verbindet die Vertrautheit und Verbreitung gängiger Webtechnologien mit den Funktionen und der Performance, die man von einer nativen Desktop-App erwartet.

Eine Java-Desktop-Anwendung mit einem Vue.js-Frontend und Tailwind CSS für das Styling wurde entwickelt. Die Lösung wurde umgesetzt, um:

  • Eine Chromium-basierte Webview in ein Java-Fenster einzubetten.
  • Vue-Ressourcen sowohl in der Entwicklungs- als auch in der Produktionsumgebung sauber zu laden.
  • Die Kommunikation zwischen Web-UI und Java-Backend über gRPC und Protobuf zu ermöglichen.

Dieses hybride Setup verbindet Java mit einem Vue.js-Frontend, sodass gängige Web-Toolchains innerhalb einer Desktop-Umgebung nutzbar sind und die Anwendung als eigenständiges Paket betrieben werden kann.

Spinner

Sending…

Sorry, the sending was interrupted

Please try again. If the issue persists, contact us at info@teamdev.com.

Read and agree to the terms to continue.

Your personal JxBrowser trial key and quick start guide will arrive in your Email Inbox in a few minutes.