Interoperability
Once a Swing application is embedded with SwingBridge (see Adding Your Swing Application), it runs as a live program inside the Vaadin session. The interoperability layer is what lets a Vaadin view talk to that program: invoke methods on it, listen to events from it, and exchange domain objects with it — type-safely, on the right thread, and without leaking listeners across navigation.
This is the API used during the second phase of an incremental migration, where individual Swing screens are replaced one at a time with native Vaadin views while the rest of the Swing application continues to run unchanged.
Mental Model
Interop is bi-directional, and each direction has its own annotation:
| Direction | What it does | Annotation |
|---|---|---|
Vaadin → Swing | A Vaadin view calls a method on a Swing class. The call is dispatched onto the AWT Event Dispatch Thread (EDT). The return value (or |
|
Swing → Vaadin | Swing code invokes a listener interface. The framework proxies the listener onto the Vaadin UI thread, where a handler method on the Vaadin view receives the event. |
|
A Maven plugin scans the Swing application’s JARs at build time and generates a typed bridge interface, proxy, and metadata class for each annotated Swing class. Vaadin code obtains a handle to that bridge through SwingBridge.interop().of(MyBridge.class) and works with the generated interface as if it were a normal Java API.
Ingredients
| Element | Role |
|---|---|
| Marks a public Swing method as callable from Vaadin. |
| Marks a handler method on a Vaadin view. |
| Marks a |
| Static accessor that returns the session-scoped |
| Returned by |
| Maven plugin that scans annotated Swing JARs and emits |
Which Page Do I Need?
Use this decision tree to find the right starting point:
-
A Vaadin view needs to call a Swing method.
→ Calling Swing Methods. Covers@ExposedMethod, the four invocation shapes, instance discovery, and theBridgeHandle.onReady/requestAsynccall sites. -
A Vaadin view needs to react to a Swing event.
→ Listening to Swing Events. Covers@VaadinCallback, the threeDispatchmodes, setter-vs-adder/remover wiring shapes, and theRegistrationcleanup pattern. -
A method on either side accepts or returns a Swing domain object (entity, DTO, value type).
→ Sharing Domain Types. This is the single most important section. Choosing the wrong strategy here causes silentClassCastExceptionor runtime classloader failures. -
Replacing a deeply-nested Swing dialog with a Vaadin one, or wiring up a Vaadin-driven cross-cutting concern.
→ Patterns and Cookbook. Vaadin-rendered LOV dialog, navigation guard withBeforeLeaveObserver, calling a bridge from a view that doesn’t host the Swing component, and theSwingBridge.runInAppContext(…)escape hatch.
Prerequisites
-
A working SwingBridge setup. If you don’t have one yet, follow Quick Start or Installation from Scratch.
-
The Swing application’s compile classpath has the
swing-bridge-annotationsJAR on it — see Adding the Annotations JAR below for how to do this in Maven, Ant, Gradle, or directly from your IDE. -
The Vaadin application’s build configures the
swing-bridge-codegen-maven-pluginso generated bridge interfaces are on the Vaadin compile classpath. See Calling Swing Methods → Build Setup.
Adding the Annotations JAR to the Swing Application
The annotations live in a single JAR with these coordinates:
| Coordinate | Value |
|---|---|
Group ID |
|
Artifact ID |
|
Version |
|
The JAR carries only the @ExposedMethod, @VaadinCallback, and @InstanceProvider annotations, plus the Invocation, Dispatch, and Discovery enums. It has no transitive dependencies and no runtime cost — it is compile-only on the Swing side. The Swing application does not need it on its runtime classpath; the embedded launch on the Vaadin side supplies the runtime classes.
The JAR is published in Vaadin’s public Maven repositories — https://maven.vaadin.com/vaadin-addons for stable releases and https://maven.vaadin.com/vaadin-prereleases for pre-releases. Downloads are anonymous; the SwingBridge license check happens later, at runtime on the Vaadin side, when the embedded Swing app starts. See License Installation for the license setup itself.
Pick the approach that matches your Swing project’s build:
Maven
Source code
XML
<repositories>
<repository>
<id>vaadin-addons</id>
<url>https://maven.vaadin.com/vaadin-addons</url>
</repository>
<!-- ... existing repositories ... -->
</repositories>
<dependencies>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>swing-bridge-annotations</artifactId>
<version>1.2.0</version>
<scope>provided</scope>
</dependency>
</dependencies>scope=provided reflects the compile-only nature of the JAR. The <repositories> block is only needed if your Swing project’s pom.xml doesn’t already inherit one from a parent.
Gradle
Source code
groovy
repositories {
maven { url = uri("https://maven.vaadin.com/vaadin-addons") }
// ... existing repositories ...
}
dependencies {
compileOnly 'com.vaadin:swing-bridge-annotations:1.2.0'
}compileOnly is the Gradle equivalent of provided.
Ant, IDE-Managed lib/, or No Formal Build Tool
Most long-running Swing codebases use Ant, IDE-managed libraries, or no formal build tool. Download the JAR directly with a browser or curl:
Source code
terminal
curl -O https://maven.vaadin.com/vaadin-addons/com/vaadin/swing-bridge-annotations/1.2.0/swing-bridge-annotations-1.2.0.jarFor a SwingBridge pre-release, swap vaadin-addons for vaadin-prereleases in the URL. The download is anonymous — no Vaadin license check at this step.
Then add the JAR to the Swing project:
-
Drop it into the project’s compile-time library folder. Wherever you keep compile-time JARs today — typically
lib/,libs/, ordependencies/next to the project. -
Reference it from the build:
-
Ant: add the JAR to the path used by the
<javac>task. Most projects expose a<path id="compile.classpath">block; add a<pathelement location="lib/swing-bridge-annotations-1.2.0.jar"/>entry inside it. -
Eclipse (with or without Ant): right-click the project → Build Path → Configure Build Path → Libraries → Add External JARs → select the JAR. If the project is shared in version control, commit the resulting
.classpathchange. -
IntelliJ IDEA: File → Project Structure → Libraries → + Java → select the JAR; assign it to the relevant module(s).
-
NetBeans: right-click the project → Properties → Libraries → Compile tab → Add JAR/Folder → select the JAR.
-
-
Verify. Open any Swing source file and confirm that this import resolves with no error:
Source code
Java
import com.vaadin.swingbridge.interop.ExposedMethod;
What’s Shipped Today
The interop runtime, the generate-bridge Maven goal, and the by-reference domain-types strategy are production-ready. Two further codegen goals exist as in-progress skeletons and are not recommended for production use yet:
| Capability | Status | Notes |
|---|---|---|
| Shipped | Stable annotation surface in |
| Shipped | Including |
| Shipped | Helper for running arbitrary code on a thread in the Swing app’s |
| Shipped | Scans JARs, infers discovery, emits bridge interface + proxy + metadata + listener-interface stubs. |
Shared domain types by reference (Type 3+) | Shipped | Add the domain JAR as a Maven |
| Roadmap | Mojo skeleton in the codebase but untested and unwired. Don’t rely on it yet. |
| Roadmap | Mojo skeleton for DTO generation + JSON marshalling. Currently requires hand-rolled DTOs as an interim. |
Gradle plugin wrapper | Not started | Maven only for now. |
Topics
- Calling Swing Methods
- Expose Swing methods with
@ExposedMethodand call them from Vaadin code through a typed bridge. - Listening to Swing Events
- Implement Swing listener interfaces with
@VaadinCallbackhandlers on a Vaadin view. - Sharing Domain Types
- Make Swing entity classes resolvable from both sides so they cross the bridge without conversion.
- Patterns and Cookbook
- Common high-level patterns for combining
@ExposedMethod,@VaadinCallback, and theSwingBridgehelpers.