Modernization Tutorial
Dieses Tutorial führt durch die Modernisierung einer bestehenden Java Swing-Anwendung durch die Integration mit webforJ mithilfe des WebswingConnector. Sie lernen, wie Sie eine traditionelle Desktop-Anwendung webbasiert zugänglich machen und schrittweise moderne Webfunktionen wie webbasierte Dialoge und interaktive Formulare mit webforJ-Komponenten hinzufügen.
Bevor Sie mit diesem Tutorial beginnen, führen Sie die Schritte Setup und Konfiguration durch, um Ihren Webswing-Server und die CORS-Einstellungen zu konfigurieren.
Der komplette Quellcode für dieses Tutorial ist auf GitHub verfügbar: webforj/webforj-webswing-integration-tutorial
Das Szenario
Stellen Sie sich vor, Sie haben eine Kundenverwaltungsanwendung, die mit Swing erstellt wurde und seit Jahren in Produktion ist. Sie funktioniert gut, aber die Benutzer erwarten jetzt Webzugang und eine moderne Schnittstelle. Anstatt von Grund auf neu zu schreiben, verwenden Sie Webswing, um sie sofort webbasiert zugänglich zu machen und schrittweise moderne Webfunktionen wie webbasierte Dialoge und Formulare mit webforJ-Komponenten hinzuzufügen.
Ausgangspunkt: die Swing-Anwendung
Die Beispiel-Swing-Anwendung ist eine Kundentabelle mit typischen CRUD-Operationen. Wie viele Unternehmens-Swing-Anwendungen folgt sie Standardmustern:
public class Application {
private List<Customer> customers;
private DefaultTableModel model;
private JTable table;
private void createTable() {
String[] columnNames = { "Name", "Firma", "E-Mail" };
model = new DefaultTableModel(columnNames, 0) {
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
};
table = new JTable(model);
table.setRowHeight(30);
table.setRowSelectionAllowed(true);
table.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) {
// Handle double-click to edit
}
}
});
}
private void showEditDialog(Customer customer) {
JTextField nameField = new JTextField(customer.getName());
JTextField companyField = new JTextField(customer.getCompany());
JTextField emailField = new JTextField(customer.getEmail());
Object[] fields = {
"Name:", nameField,
"Firma:", companyField,
"E-Mail:", emailField
};
int result = JOptionPane.showConfirmDialog(null, fields, "Kunden bearbeiten",
JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
}
}
Diese Anwendung funktioniert perfekt als Desktop-Anwendung, fehlt jedoch der Webzugang. Benutzer müssen Java installieren und die JAR-Datei lokal ausführen.
Schritt 1: Webswing-kompatibel machen
Der erste Schritt besteht darin, die Swing-Anwendung dazu zu bringen, zu erkennen, ob sie unter Webswing läuft. Dadurch kann sie ihr Verhalten anpassen, ohne die Desktop-Kompatibilität zu beeinträchtigen.
Erkennen der Webswing-Umgebung
Fügen Sie die Webswing-API-Abhängigkeit zu Ihrem Swing-Projekt hinzu:
<dependency>
<groupId>org.webswing</groupId>
<artifactId>webswing-api</artifactId>
<version>25.1</version>
</dependency>
Ändern Sie dann Ihre App, um die Webswing-Laufzeit zu erkennen:
private void initWebswing() {
api = WebswingUtil.getWebswingApi();
isWebswing = api != null;
if (isWebswing) {
setupWebswingListeners();
}
}
Die zentrale Erkenntnis hierbei ist, dass WebswingUtil.getWebswingApi() null zurückgibt, wenn es als reguläre Desktop-Anwendung läuft, wodurch Sie eine Dualmodus-Kompatibilität aufrechterhalten können.
Verhalten für die Webbereitstellung anpassen
Mit der Erkennung können Sie jetzt das Verhalten der App anpassen. Die wichtigste Änderung betrifft die Handhabung von Benutzerinteraktionen:
private void handleDoubleClick(MouseEvent e) {
int row = table.rowAtPoint(e.getPoint());
if (row >= 0 && row < customers.size()) {
Customer customer = customers.get(row);
if (isWebswing) {
api.sendActionEvent("select-customer", gson.toJson(customer), null);
} else {
showEditDialog(customer);
}
}
}
Durch das Verzweigen des Verhaltens je nach Wert von isWebswing kann der Code beide Umgebungen handhaben.
Schritt 2: den webforJ-Wrap erstellen
Jetzt, da die Swing-Anwendung über Ereignisse kommunizieren kann, erstellen Sie eine webforJ-App, die die Swing-Anwendung einbettet und moderne Webfunktionen wie webbasierte Dialoge und Formulare hinzufügt.
Einrichten des Connectors
Das WebswingConnector-Element bettet Ihre in Webswing gehostete App innerhalb einer webforJ-Ansicht ein:
@Route("/")
public class CustomerTableView extends Composite<FlexLayout> {
private final FlexLayout self = getBoundComponent();
public CustomerTableView(@Value("${webswing.connector.url}") String webswingUrl) {
WebswingConnector connector = new WebswingConnector(webswingUrl);
connector.setSize("100vw", "100vh");
self.add(connector);
}
}
Der Connector verbindet sich mit Ihrem Webswing-Server und stellt einen bidirektionalen Kommunikationskanal her.
Ereignisse aus Swing verarbeiten
Wenn die Swing-Anwendung Ereignisse sendet (z. B. wenn ein Benutzer eine Zeile doppelklickt), empfängt der Connector diese:
connector.onAction(event -> {
switch (event.getActionName()) {
case "select-customer":
event.getActionData().ifPresent(data -> {
JsonObject customer = JsonParser.parseString(data).getAsJsonObject();
CustomerForm dialog = new CustomerForm(customer);
self.add(dialog);
dialog.onSave(() -> {
Gson gson = new Gson();
connector.performAction("update-customer", gson.toJson(customer));
});
});
break;
}
});
Jetzt sehen die Benutzer anstelle des Swing-Dialogs ein modernes Webformular, das mit webforJ-Komponenten erstellt wurde.
Schritt 3: bidirektionale Kommunikation
Die Integrationskraft wird deutlich, wenn die Kommunikation in beide Richtungen fließt. Die webforJ-Anwendung kann Aktualisierungen an die Swing-Anwendung senden, wodurch beide UIs synchronisiert bleiben.
Updates an Swing senden
Nachdem der Benutzer einen Kunden im webforJ-Dialog bearbeitet hat:
dialog.onSave(() -> {
// Aktualisierten Kunden zurück an Swing senden
connector.performAction("update-customer", gson.toJson(customer));
});
Updates in Swing verarbeiten
Die Swing-Anwendung hört auf diese Updates und aktualisiert ihre Anzeige:
private void setupWebswingListeners() {
api.addBrowserActionListener(event -> {
if ("update-customer".equals(event.getActionName())) {
Customer updated = gson.fromJson(event.getData(), Customer.class);
updateCustomer(updated);
}
});
}
Architekturvorteile
Dieser Ansatz bietet mehrere Vorteile im Vergleich zu einer vollständigen Neuentwicklung:
Sofortige Webbereitstellung
Ihre Swing-Anwendung wird sofort webbasiert zugänglich, ohne dass Codeänderungen erforderlich sind. Benutzer können über einen Browser darauf zugreifen, während Sie an Verbesserungen arbeiten.
Fortschreitende Verbesserung
Beginnen Sie damit, nur den Bearbeitungsdialog zu ersetzen, und ersetzen Sie dann schrittweise mehr Komponenten:
- Phase 1: Bettet die gesamte Swing-Anwendung ein, ersetzt nur den Bearbeitungsdialog
- Phase 2: Fügt webforJ-Navigation und -Menüs um die eingebettete Anwendung herum hinzu
- Phase 3: Ersetzt die Tabelle durch eine webforJ-Tabelle, wobei Swing für unverzichtbare Funktionen beibehalten wird
- Phase 4: Ersetzt schließlich alle Swing-Komponenten
Risikominderung
Da die ursprüngliche Swing-Anwendung funktionsfähig bleibt, können Sie:
- Bei Bedarf auf die Desktop-Bereitstellung zurückgreifen
- Neue Funktionen neben bestehenden testen
- Benutzer schrittweise migrieren
- Die gleiche Geschäftslogik beibehalten