Overslaan naar hoofdinhoud

Swing modernization

Swing to the web, one screen at a time

Your Swing, JavaFX or SWT app runs in a web browser without changes to its source. Then you build new screens in webforJ around it and replace the old ones at your own pace. The Java team and the code stay.

Desktop toolkits: Swing, JavaFX and SWT
3
Source changes to run in a browser
0
Customers
  • CustomersSwing
  • OrderswebforJ
  • ReportsSwing
Swing app, streamed
Customer Table
FileEditView
NameTeamCity
Hyyan Abo FakherSalesBerlin
Matthew HawkinsSupportBoston
Eric HandtkeFinanceHamburg
Ben BrennanSalesDenver
Garrison OsteenSupportAustin
Lauren AlamoFinancePhoenix

Edit customer

CancelSave
webforJ dialog
A double click in the Swing table opens a webforJ dialog instead of the old Swing one. Both run in the same browser tab.

What stays the same

Only the screens change

webforJ is the full-stack Java framework for business web apps: you build the whole app, screens included, in Java. So moving a Swing app means moving its screens, and everything under them carries over.

What changes

The screens. You move them one at a time, in the order that matters to your business, while the rest of the Swing app keeps running in the same browser tab.

  1. 01

    The team

    The people who maintain the Swing app today build the web screens in Java. There is no second team and no front-end toolchain to learn.

  2. 02

    The code

    Webswing runs the app as it is. The same code base keeps working as a desktop app and in the browser, so you maintain one app, not two.

  3. 03

    The logic

    Domain classes, services and validation rules that have nothing to do with javax.swing are called straight from the new screens. They do not become endpoints first.

  4. 04

    The toolchain

    Maven, your IDE, your debugger and your existing tests continue to apply.

The move, in three phases

Step through the move from desktop to web

Each phase ships something users can see. Pick a phase to see the screen at that point and the code that makes it work.

Customer Table
FileEditView
NameTeamCity
Hyyan Abo FakherSalesBerlin
Matthew HawkinsSupportBoston
Eric HandtkeFinanceHamburg
Ben BrennanSalesDenver
Garrison OsteenSupportAustin
Lauren AlamoFinancePhoenix

Run the desktop app in the browser

Webswing runs your Swing, JavaFX or SWT app on the server and streams its interface to the browser as HTML5 canvas. Mouse and keyboard input go back to the real app. The source code does not change.

Embed it in a webforJ view with WebswingConnector. The connector connects to the Webswing server when it is added to the page.

SwingAppView.java
@Route
public class SwingAppView extends Composite<Div> {
private final Div self = getBoundComponent();
private WebswingConnector connector;

public SwingAppView() {
// Initialize the connector with your Webswing application URL
connector = new WebswingConnector("http://localhost:8080/myapp/");

// Set the display dimensions
connector.setSize("100%", "600px");

// Add to the view container
self.add(connector);
}
}

Phase 1 of 3

Two-way communication

Old and new screens talk to each other

A message is an action: a name, an optional string payload and an optional binary payload. The name is yours to invent. Both ends are plain Java, so nobody writes browser script for the exchange.

  1. 1

    Swing announces

    A double click sends select-customer with the row as JSON. On the desktop the same click still opens the Swing dialog.

    Application.java (Swing)
    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);
    }
    }
    }
    CustomerBridgeView.java (webforJ)
    connector.onAction(e -> {
    switch (e.getActionName()) {
    case "select-customer" -> e.getActionData().ifPresent(this::openEditor);
    case "export-ready" -> e.getActionBinaryData()
    .ifPresent(d -> status.setText("Got " + d.length() + " characters"));
    default -> { }
    }
    });
  2. 2

    webforJ replies

    On save the web form sends update-customer back, and the Swing app refreshes its table. Neither side calls into the other one's internals.

    Application.java (Swing)
    private void setupWebswingListeners() {
    api.addBrowserActionListener(event -> {
    if ("update-customer".equals(event.getActionName())) {
    Customer updated = gson.fromJson(event.getData(), Customer.class);
    updateCustomer(updated);
    }
    });
    }
    CustomerTableView.java (webforJ)
    dialog.onSave(() -> {
    // Send updated customer back to Swing
    connector.performAction("update-customer", gson.toJson(customer));
    });

Send commands into Swing

performAction() sends a name alone or a name with data. The Swing app decides what each name means.

Sending actions
// Trigger a refresh in the Swing application from webforJ
connector.performAction("refresh");

// Send a command with data from webforJ
connector.performAction("selectRecord", "12345");

Know when Swing is ready

onInitialize fires when the connection is ready. onStart fires when the Swing app has fully loaded. Send your first action from onStart.

Lifecycle events
connector.onInitialize(e -> status.setText("Connected"));
connector.onStart(e -> status.setText("Swing app running"));

Port with an AI assistant

Let an assistant port it, screen by screen

Moving screen by screen is repetitive work, and that suits an AI coding assistant. The webforJ AI plugin connects it to the webforJ MCP server and to Agent Skills, structured workflows that tell it when to use those tools, in what order, and how to validate the result.

  1. 1

    Give it one Swing screen

    Ask for the webforJ equivalent that calls your existing services.

  2. 2

    It checks the real API

    The MCP server looks up webforJ documentation and API details on demand, instead of guessing.

  3. 3

    You review and test

    Compare behavior against the Swing original, then move on to the next screen.

How to start

From a JAR file to a page in the browser

You need a Swing, JavaFX or SWT app packaged as a JAR file, the Webswing server and webforJ 25.10 or later.

  1. 1

    Download and start Webswing

    Download Webswing, extract the archive, then start the server with the script for your platform. It answers on http://localhost:8080.

    Webswing
    webswing.sh
  2. 2

    Register your app

    In the admin console at http://localhost:8080/admin, set the application name, main class, classpath, JVM arguments and home directory. The app is then served at http://localhost:8080/[app-name]/.

    CORS
    Add your webforJ app's origin to Allowed Origins, for example http://localhost:8090.
    Ports
    Both typically use 8080. Change one of them so they do not conflict.
  3. 3

    Add the dependency

    The webforj-webswing module provides WebswingConnector and the classes around it.

    <dependency>
    <groupId>com.webforj</groupId>
    <artifactId>webforj-webswing</artifactId>
    <version>${webforj.version}</version>
    </dependency>
  4. 4

    Embed and configure

    Add a WebswingConnector to a view, as in phase 1. WebswingOptions changes its behavior, for example hiding the logout button when your webforJ app handles sign in.

    WebswingConnector connector = new WebswingConnector("http://localhost:8080/myapp/");

    WebswingOptions options = new WebswingOptions()
    .setDisableLogout(true); // Hide the logout button

    connector.setOptions(options);