SwingBridge
- Prerequisites
- License Installation
- Project Setup
- Add Your Swing Application
- Create a Vaadin View for Your Swing Application
- Running and Debugging
- What Happens Under the Hood
- Frequently Asked Questions
- IDE Remote Debug Configuration
Your existing Swing application runs in a web browser without requiring you to rewrite any of your Swing code. Users interact with it through their browser while the actual Swing application runs on the server.
The following guide helps you utilize SwingBridge to integrate your Swing applications into a modern web interface.
Prerequisites
Before getting started, ensure that the following requirements are met:
-
Java 21 or later: SwingBridge requires Java 21 as the minimum supported version, consistent with the Vaadin 25+ series.
-
Maven (optional): Required only if you choose to set up a project from scratch. The skeleton starter project includes Maven Wrapper scripts, so a separate Maven installation is not needed for that approach.
License Installation
SwingBridge requires a commercial Vaadin subscription or a trial license. You can obtain one automatically or install it manually. Automatic license installation is the preferred choice. You are asked to either create a new vaadin.com account or login to an existing one in the following process.
Automated Installation
Once you launch your application that utilizes SwingBridge or any other commercial Vaadin component, you are asked to login to Vaadin.com This process downloads the relevant files to the directory shown below and the application proceeds to execute the commercial components automatically. You may proceed with the Project Installation section if you prefer this approach.
Source code
filesystem
%userprofile%\.vaadin\proKeyfilesystem
filesystem
filesystem
Manual Installation
Create a Vaadin account if you don’t have one by visiting https://vaadin.com/register
Under the section, click Start Trial button to start a trial License if you don’t have an active subscription.
Follow the instructions on “Licenses” section after logging in to your account to make sure you have a valid license, or at least a trial license (proKey and userKey files) in the following directory:
Source code
filesystem
%userprofile%\.vaadin\filesystem
filesystem
filesystem
For more information about Licensing please see Licensing Documentation
Project Setup
You can set up a SwingBridge project in two ways: use the skeleton starter project, which includes sample applications and preconfigured settings, or set up a project from scratch. The skeleton starter is the recommended approach when experiencing SwingBridge for the first time. It includes Maven Wrapper scripts and binaries, so you do not need to install Maven separately.
Using the Skeleton Starter
Clone or download the skeleton starter project from GitHub:
Source code
terminal
git clone https://github.com/vaadin/skeleton-starter-vaadin-swing-bridge.git
cd skeleton-starter-vaadin-swing-bridgeThis project comes with sample Swing applications, Maven Wrapper, and all necessary Maven configuration ready to go. Run the project in development mode:
Source code
terminal
./mvnw spring-boot:runterminal
terminal
terminal
Visit http://localhost:8888 to see the sample applications running inside SwingBridge.
The project uses an applibs directory where Swing application JAR files and their dependencies are placed. All files in this folder are automatically available on the SwingBridge classpath.
|
Note
|
The |
Setting Up from Scratch
Add the following parent section, properties, and dependencies to your pom.xml:
Source code
pom.xml
pom.xml<properties>
<maven.compiler.source>21</maven.compiler.source>
<vaadin.version>25.1.0-beta1</vaadin.version>
<swing-bridge.version>1.0.0</swing-bridge.version>
<swing-bridge.path>${settings.localRepository}/com/vaadin</swing-bridge.path>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>4.0.3</version>
<relativePath/>
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-bom</artifactId>
<version>${vaadin.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>swing-bridge-patch</artifactId>
<version>${swing-bridge.version}</version>
</dependency>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>swing-bridge-graphics</artifactId>
<version>${swing-bridge.version}</version>
</dependency>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>swing-bridge-flow</artifactId>
<version>${swing-bridge.version}</version>
<exclusions>
<exclusion>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j2-impl</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin</artifactId>
</dependency>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-dev</artifactId>
<optional>true</optional>
</dependency>
</dependencies>SwingBridge requires certain JVM flags so that Maven can access internal Java modules during compilation. Create a .mvn/jvm.config file in the project root with the following content:
Source code
.mvn/jvm.config
.mvn/jvm.config--add-exports=java.desktop/sun.font=ALL-UNNAMED
--add-exports=java.desktop/sun.awt=ALL-UNNAMED
--add-exports=java.desktop/sun.awt.dnd=ALL-UNNAMED
--add-exports=java.desktop/sun.awt.dnd.peer=ALL-UNNAMED
--add-exports=java.base/sun.nio.cs=ALL-UNNAMED
--add-exports=java.desktop/sun.java2d=ALL-UNNAMED
--add-exports=java.desktop/sun.java2d.pipe=ALL-UNNAMED
--add-exports=java.desktop/sun.awt.datatransfer=ALL-UNNAMED
--add-exports=java.desktop/sun.awt.image=ALL-UNNAMED
--add-exports=java.desktop/java.awt.peer=ALL-UNNAMED
--add-exports=java.desktop/java.awt.dnd=ALL-UNNAMED
--add-exports=java.desktop/java.awt.dnd.peer=ALL-UNNAMED
--add-exports=java.desktop/sun.print=ALL-UNNAMED
--add-exports=java.desktop/sun.swing=ALL-UNNAMED
--add-opens=java.desktop/java.awt.event=ALL-UNNAMED
--add-opens=java.desktop/sun.awt=ALL-UNNAMED
--add-reads=java.desktop=ALL-UNNAMEDThese flags are applied to the Maven JVM process itself, allowing the compiler to access the internal java.desktop module APIs that SwingBridge depends on. This is separate from the runtime JVM arguments configured in the build plugin below.
To launch the application through Maven CLI, add the following build plugin to your pom.xml:
Source code
pom.xml
pom.xml<build>
<defaultGoal>spring-boot:run</defaultGoal>
<plugins>
<plugin>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-maven-plugin</artifactId>
<version>${vaadin.version}</version>
<executions>
<execution>
<goals>
<goal>prepare-frontend</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<!-- all JVM flags as one space-separated string -->
<jvmArguments>
--patch-module java.desktop=${swing-bridge.path}/swing-bridge-patch/${swing-bridge.version}/swing-bridge-patch-${swing-bridge.version}.jar
-Xbootclasspath/a:${swing-bridge.path}/swing-bridge-graphics/${swing-bridge.version}/swing-bridge-graphics-${swing-bridge.version}.jar
--add-reads=java.desktop=ALL-UNNAMED
--add-exports=java.desktop/sun.font=ALL-UNNAMED
--add-exports=java.desktop/sun.awt=ALL-UNNAMED
--add-exports=java.desktop/sun.awt.dnd=ALL-UNNAMED
--add-exports=java.desktop/sun.awt.dnd.peer=ALL-UNNAMED
--add-exports=java.base/sun.nio.cs=ALL-UNNAMED
--add-exports=java.desktop/sun.java2d=ALL-UNNAMED
--add-exports=java.desktop/sun.java2d.pipe=ALL-UNNAMED
--add-exports=java.desktop/sun.awt.datatransfer=ALL-UNNAMED
--add-exports=java.desktop/sun.awt.image=ALL-UNNAMED
--add-exports=java.desktop/java.awt.peer=ALL-UNNAMED
--add-exports=java.desktop/java.awt.dnd=ALL-UNNAMED
--add-exports=java.desktop/java.awt.dnd.peer=ALL-UNNAMED
--add-exports=java.desktop/sun.print=ALL-UNNAMED
--add-exports=java.desktop/sun.swing=ALL-UNNAMED
--add-opens=java.desktop/java.awt.event=ALL-UNNAMED
--add-opens=java.desktop/sun.awt=ALL-UNNAMED
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005
</jvmArguments>
<!-- JVM -D system properties -->
<systemPropertyVariables>
<java.awt.headless>false</java.awt.headless>
<!--<applibs.dir>${project.basedir}/some-lib-dir</applibs.dir>-->
</systemPropertyVariables>
</configuration>
</plugin>
</plugins>
</build>Add Your Swing Application
The following applies to both cases above: either you cloned from GitHub or created from scratch.
Copy your Swing application’s main jar binary and all its dependencies into the applibs folder in the project you created in the first section. The sample Swing application’s jar file is included if you cloned the skeleton project directly from GitHub. All files placed in this folder are visible on the SwingBridge classpath.
Create a Vaadin View for Your Swing Application
Refer to the class that contains the main() method of your Swing application inside a Vaadin View.
Source code
Java
@Route("myapp")
public class MyAppView extends VerticalLayout {
public MyAppView() {
add(new SwingBridge("com.mycompany.swingapp.MySwingAppMain"));
setSizeFull();
}
}Start the server:
Source code
terminal
mvn spring-boot:runNavigate to http://localhost:8888 to see the application. If you configured a custom port in your project (the Spring Boot default is 8080), navigate to that port instead.
Running and Debugging
Running from the Command Line
SwingBridge requires special JVM flags to access internal Java modules. Because of this, running the application by clicking the green play button in IntelliJ IDEA or the equivalent in VS Code is not supported at this time.
To run the application, use Maven from the command line as described in the skeleton starter or from scratch sections.
|
Note
|
Hotswap Agent and Spring Boot DevTools automatic restart are not fully supported with SwingBridge yet. If you detect unexpected behavior, try running the application without them. |
Remote Debugging
After starting the application through Maven, you can debug it using remote debugging. The skeleton starter project already includes the necessary JVM argument for this. If you set up from scratch, add the following to the <jvmArguments> section in your spring-boot-maven-plugin configuration:
Source code
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005For IDE-specific setup instructions, see IntelliJ IDEA and VS Code.
What Happens Under the Hood
Once you’ve set up your SwingBridge subclass, the framework handles:
-
Launching your Swing application in the background when the component attaches
-
Capturing the UI as images and streaming them to the browser
-
Handling user interactions like clicks, keyboard input, and window resizing
-
Managing dialogs and popups that your Swing application creates
-
Updating the display continuously so users see a live view of your application
Frequently Asked Questions
What is SwingBridge?
SwingBridge is a Vaadin component that allows you to run existing Swing applications in a web browser without rewriting them. It captures the Swing UI as images and streams them to the browser while handling user interactions.
Does the existing Swing code need modification?
Swing applications originally are designed and built with single tenancy in mind. Local resource usages like filesystem access, serial devices etc. should be refactored in order to achieve full multi-tenancy. Vaadin has relevant tooling to automate code refactoring.
What Swing components are supported?
All standard Swing components are supported, as well as your customized Swing components.
- JFrame, JDialog, JWindow
- JPopupMenu and combo box popups
- JFileChooser (with special upload handling)
- Tooltips
- All standard Swing widgets (buttons, text fields, tables, etc.)
How does SwingBridge work?
SwingBridge runs your Swing application on the server and continuously inspects the Swing UI for changes. As soon as a change is detected, dirty regions are streamed to the browser to keep the updates as lightweight as possible. User interactions (clicks, keyboard input) are sent back to the server and replayed on the actual Swing components.
IDE Remote Debug Configuration
IntelliJ IDEA
To set up remote debugging in IntelliJ IDEA:
-
Open .
-
Click the + button and select Remote JVM Debug.
-
Set the Name to something descriptive, such as
SwingBridge Remote Debug. -
Ensure Debugger mode is set to Attach to remote JVM.
-
Set Host to
localhostand Port to5005. -
Click OK to save the configuration.
Start the application through Maven first, then launch this debug configuration. The debugger attaches to the running application, and you can set breakpoints and step through code as usual.
VS Code
To set up remote debugging in VS Code:
-
Open or create the
.vscode/launch.jsonfile in your project. -
Add the following configuration:
Source code
JSON
{ "type": "java", "name": "SwingBridge Remote Debug", "request": "attach", "hostName": "localhost", "port": 5005 } -
Start the application through Maven first.
-
Open the Run and Debug view and select SwingBridge Remote Debug.
-
Click the green play button to attach the debugger.
You can now set breakpoints and debug the running application.