What’s Changed & Migration

This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production.

The reference material consulted while preparing these pages is listed in the section bibliography.

This page is written against GWT 2.13.1 (2026-06-19), gwt-maven-plugin 1.3.0 (2026-05-31), JDK 21 with -sourceLevel 17 and Jakarta Servlet 6.0 (the stack the modular-webapp archetype 2026.6.22 generates), as of 2026-10-09; the release dates are those of the official release notes. It is about everything that moved: the language and tooling jumps from GWT 1.x to 2.x, what each 2.x release changed, how to migrate an existing project (build and server code: Maven coordinates, servlets, plugin; client code compiled to JavaScript: JSNI, Elemental, CSS), and where older books, tutorials and even some official pages no longer match the toolkit. It is the page to open when you inherit an application written for GWT 1.x to 2.8, when a tutorial or the 2007 first edition of GWT in Action tells you something that does not compile, and when you have to decide the order of an upgrade. Each topic page of this section has its own "outdated" and "recent changes" notes; this page collects them in one place.

Where to look first

Table 1. Starting point and the section to read
You have Read

A build that still uses com.google.gwt coordinates, a gwt-maven-plugin from org.codehaus.mojo, or Ant

com.google.gwt to org.gwtproject, the plugin recipe and Build Tools: Maven & Gradle

A server on Tomcat 10+, Jetty 11+, Spring Boot 3+ or any Jakarta EE 9+ container

javax to jakarta

Code with /*-{ ... }-*/ native methods, JavaScriptObject overlays or the first elemental.* library

JSNI to JsInterop and Elemental to Elemental2

.css files behind CssResource, ImageBundle or listener interfaces

CSS to GSS and the old-to-current tables further down

A book or tutorial that no longer works

Outdated in older material, row by row

A statement of this section that contradicts an official page

Corrections and deviations

The 2.x line on one page

timeline title GWT milestones that change how applications are written 2009 : 2.0 in-browser development mode, UiBinder, ClientBundle, code splitting, HtmlUnit tests 2010 : 2.1 cell widgets, RequestFactory, Activities and Places 2012 : 2.5 Super Dev Mode experimental, Elemental experimental, ARIA library 2014 : 2.7 Super Dev Mode is the default, GSS and JsInterop experimental 2016 : 2.8 Java 8 syntax, JsInterop and GSS graduate 2020 : 2.9 Elemental2 and jsinterop-base compatible, Elemental deprecated 2022 : 2.10 org.gwtproject coordinates, IE 8 to 10 dropped, Java 17 tested 2024 : 2.11 Jakarta artifacts : 2.12 Java 12 to 17 language features 2026 : 2.13 static-only DevMode server, JFR events : 2.13.1 bug fixes

The long gaps are real: after 2.8.2 (2017-10-19) the project shipped 2.9.0 in 2020, 2.10.0 in 2022 and 2.11.0 in 2024, and 2.13.1 on 2026-06-19 is the newest release. The open milestone list of the GitHub repository and the roadmap name the direction: bring Java language features and the JRE emulation up to Java 21, and explore some J2CL-only JsInterop features in the GWT compiler. There is no GWT 3 release (J2CL & the Future).

From GWT 1.x to 2.x

The first edition of the book this section is compared with describes GWT 1.3 and 1.4 (2007) and Java 1.4 client code. Moving from that world to GWT 2 is less one upgrade than five: the language level, the event model, the development loop, the resources and the UI toolkit.

Table 2. What a GWT 1.x application looked like and what replaced it
Area GWT 1.x GWT 2.x (and 2.13.1) Since

Language

Java 1.4 on the client: no generics, enums or annotations; RPC collections described with the @gwt.typeArgs Javadoc annotation

Java 5 features arrived with 1.5 (generics, enums, annotations); 2.6 made Java 7 the default, 2.8 Java 8 syntax, 2.12 Java 12 to 17 syntax (records, text blocks, switch expressions, instanceof patterns)

1.5, 2.6, 2.8, 2.12

Events

Listener interfaces (ClickListener, KeyboardListener, ChangeListener, TableListener, FormHandler, WindowResizeListener) and EventPreview

Handlers and HandlerRegistration (ClickHandler, addClickHandler, Window.addResizeHandler, Event.addNativePreviewHandler). The listener types are still present in the 2.13.1 gwt-user jar, all @Deprecated, with Javadoc that names the handler to use

1.6 (deprecation of the listeners)

Images and resources

ImageBundle with the @gwt.resource Javadoc tag

ClientBundle with ImageResource, CssResource, DataResource, TextResource and @Source annotations. ImageBundle is @Deprecated ("replaced by ClientBundle") but still compiles

2.0

Development loop

Hosted mode: a special embedded browser started by GWTShell (later HostedMode)

2.0: "development mode" in your normal browser through a plugin, started by com.google.gwt.dev.DevMode. 2.5: Super Dev Mode (JavaScript compiled incrementally, debugged with source maps). 2.7.0 RC1: Super Dev Mode is the default. 2.8.0: classic development mode deprecated. Today: gwt:codeserver and any servlet container

2.0, 2.5, 2.7, 2.8

Layout

Table-based panels (DockPanel, HorizontalSplitPanel, StackPanel) sizing themselves from table cells

Layout panels (LayoutPanel, RootLayoutPanel, DockLayoutPanel, SplitLayoutPanel, TabLayoutPanel, StackLayoutPanel) built on CSS, plus UiBinder and plain CSS layout. DockPanel, StackPanel, TabPanel and DeckPanel are not deprecated in 2.13.1; HorizontalSplitPanel and VerticalSplitPanel are

2.0

UI construction

Widgets assembled in Java code only

UiBinder (*.ui.xml with @UiField, @UiHandler) for declarative UIs; Cell widgets (CellTable, CellList, DataGrid since 2.4); the Editor framework; MVP with Activities and Places

2.0, 2.1, 2.4, 2.1

Startup and size

One monolithic script

GWT.runAsync code splitting, compile reports, linkers and the xsiframe bootstrap

2.0, 2.5

Testing

GWTTestCase on SWT and native browser code

GWTTestCase on HtmlUnit by default, JUnit 4 style test classes, GWTTestCase arguments -prod and -runStyle

2.0

Distribution

Platform-specific jars (gwt-dev-windows.jar) in an SDK zip

One platform-independent gwt-dev.jar; since 2.10.0 everything is on Maven Central under org.gwtproject

2.0, 2.10

Project layout

public, client, server directories and a hosted-mode servlet container started by the toolkit

The Maven multi-module layout generated by the modular-webapp archetype (-shared, -client, -server), the module descriptor under src/main/module.gwt.xml, the server run by Jetty or Spring Boot

2.10, 2.13

Three consequences of that table deserve a sentence each, because they are what breaks an old code base first.

  • The 2.0 notes introduce the terms "development mode" and "production mode" for what 1.x called hosted mode and web mode. Command lines changed with them: -web became -prod, -portHosted became -codeServerPort, and junitCreator disappeared into webAppCreator -junit. webAppCreator is itself deprecated since 2.11.0 (see Getting Started).

  • Deferred binding and the module XML survived the jump unchanged in spirit: a 1.x module descriptor with <inherits>, <source>, <entry-point>, <servlet> still parses, but its user.agent assumptions do not (see the browser matrix below).

  • Server code is Java, not GWT. A 1.x servlet that extends RemoteServiceServlet still works if its javax.servlet container still exists; on a Jakarta container it needs the recipe below.

GWT 2.0 to 2.13.1: release highlights

Table 3. Releases of the 2.x line and what they changed
Release Date Highlights that affect application code or builds

2.0.0

2009-12-09

In-browser development mode (the GWT Developer Plugin) replaces the hosted browser; GWT.runAsync code splitting; UiBinder; ClientBundle; HtmlUnit for GWTTestCase; platform-independent gwt-dev.jar; layout panels; compile reports (then called SOYC) behind -compileReport and written to the extra directory

2.1.0

2010-10-27

Cell widgets and an app framework for large applications (RequestFactory, Activities and Places); 2.1.1 (2010-12-17) adds a service layer to RequestFactory

2.2.0

2011-02-11

HTML5 Canvas, Audio and Video, touch events, bidi support, sortable CellTable, more lenient SafeHtml template parser; Java 1.5 deprecated

2.3.0

2011-05-02

IE9 support; HTML5 local storage; UiBinder.useSafeHtmlTemplates is off by default and the compiler warns about it

2.4.0

2011-09-07

DataGrid with a fixed header; persistent unit cache. The 2.4 betas and release candidates carried an XSS problem that was completely fixed only in 2.5 (see SafeHtml & XSS)

2.5.0

2012-10-25

Super Dev Mode (experimental); Elemental (experimental); the ARIA library; fragment merging; source maps; SafeHtml in the user library; UiBinder.useLazyWidgets on by default; Tree.addItem(String) deprecated in favour of addTextItem. 2.5.1 (2013-03-09): fix for a GWTTestCase XSS file, DirectInstallLinker for pages that forbid inline scripts, RequestBuilder.withCredentials()

2.6.0

2014-01-23

Java 7 is the default language level; the Super Dev Mode hook is on by default (RC4); the ie6 permutation is disabled and ie10 added; @GwtIncompatible; Widget.addBitlessDomHandler; Jetty 8.1, Servlet 3.0, HtmlUnit 2.13

2.7.0

2014-11-20 (RC1 2014-10-30)

Super Dev Mode is the default and DevMode starts it automatically; experimental GSS (CssResource.enableGss) and JsInterop (-XjsInteropMode); logging defaults to SEVERE on the browser console; deRPC removed; IFrameLinker and XSLinker deprecated; History.replaceItem()

2.8.0

2016-10-20 (Beta1 2015-12-03)

Java 8 syntax and library emulation; JsInterop graduates from experimental (the final specification); GSS is no longer experimental and legacy CssResource syntax is deprecated; classic development mode deprecated; client-side JSR-303 validation deprecated; split-out jsinterop-annotations jar. 2.8.1 (2017-04-24): -includeJsInteropExports/-excludeJsInteropExports. 2.8.2 (2017-10-19): runs on a Java 9 JRE, CSP compliance work

2.9.0

2020-05-13

Compiles with jsinterop-base 1.0.0, Elemental2 1.0.0 and jsinterop-annotations 2.0.0 (everything but @JsAsync and @JsEnum is compatible with J2CL); source levels 9, 10 and 11; running the tools on Java 7 officially dropped; Elemental (1) deprecated; script nonces propagated by ScriptInjector

2.10.0

2022-06-09

Maven groupId changes to org.gwtproject (the last release under com.google.gwt); HtmlUnit 2.55.0; Java 17 tested; IE 8, 9 and 10 dropped; 2.10.1 (2024-01-09) backports the JPA/JDO decision of 2.11

2.11.0

2024-01-09

Jakarta artifacts (gwt-servlet-jakarta, requestfactory-server-jakarta); JPA/JDO "enhanced classes" no longer serializable by default over GWT-RPC (with a warning); Java 21 tested; Java 11 collections and streams emulation; DevMode as an application server and webAppCreator deprecated; development moves to GitHub pull requests

2.12.0

2024-10-29

Java 12 to 17 language features (text blocks, instanceof patterns, records, switch expressions); tools need Java 11; source maps on in all browsers and they include the source contents; CSP fixes in linkers and Dev Mode plus CSP workarounds for GWT-RPC payloads; -XfragmentMerge has no effect; many dead flags removed; the unload event deprecated. 2.12.1 (2024-11-12) and 2.12.2 (2025-03-03) fix switch compilation and a Window.onClosing() regression

2.13.0

2026-02-11

DevMode server serves static files only by default; JFR events replace SpeedTracer; -strict accepted in test arguments; gwt.validation.ignoreXml; Java 9+ emulation additions; Jetty 9.4.58; breaking: String.split uses Java 8 semantics, Collectors.toMap throws on a null value, AccessControlException emulation removed. Likely the last release whose compiler and tools run on Java 11

2.13.1

2026-06-19

Four bug fixes: files that cannot be deleted on Windows no longer fail the build, simpler iframe loading in Firefox, Objects.equals for record fields with null (a wrong equals before), the GWT version and commit in JFR output

Behaviour changes that compile but behave differently

These are the changes that no compiler error will report. Two are in the 2.13.0 notes under "Breaking Changes"; the others are consequences of defaults that moved.

Table 4. Silent changes and how to check your code
Change What it means for your code Check

String.split emulation follows Java 8 semantics for empty entries (2.13.0)

Code that split on a delimiter and relied on the old emulated handling of empty leading or trailing entries can return a different array

Search for split( in client and shared code; shared code now matches the JVM behaviour

Collectors.toMap throws when a value is null (2.13.0)

The emulation matches the JVM (though not its Javadoc); a map built from nullable values fails at run time in the browser

Search for toMap(; filter nulls or use a merge-friendly collector

AccessControlException emulation removed (2.13.0)

A class that catches or throws it in shared code stops compiling for the client

Keep it behind a server-only class or @GwtIncompatible

Source level (2.12.0 and 2.13.x)

The command-line compiler’s -sourceLevel defaults to 1.8, so Java 12 to 17 syntax in a Java 17 code base is rejected unless the build passes -sourceLevel 17. auto resolves to the level of the running JVM

The archetype sets <sourceLevel>17</sourceLevel> in gwt-maven-plugin (the plugin’s own default comes from maven.compiler.source); set it in any hand-written build

-failOnError (alias -strict since 2.13.0)

Without it the compiler can hide JSNI and overlay errors behind "Ignored N units with compilation errors in first pass"; the archetype turns it on

Make sure failOnError is true in CI

DevMode as application server (2.13.0)

The embedded Jetty 9 launcher is no longer the default and is "due to be removed". A project that relied on gwt:devmode serving its servlets must split the server out or supply a ServletContainerLauncher

Run the server (Jetty or Spring Boot) separately and use gwt:codeserver

JPA/JDO enhanced classes over GWT-RPC (2.10.1 and 2.11.0)

Entities that were enhanced by an ORM are no longer serializable by default; a warning explains it (the -Dgwt.enhancedClasses.enabled=true switch restores the old behaviour at your own risk)

Send plain DTOs instead

Flags and classes that are gone

Build scripts and run configurations written for 2.8 to 2.11 fail on options that no longer exist. The 2.12.0 notes list the removed, unused compiler flags; the 2.13.0 notes list removed classes.

Table 5. Removed in 2.12.0 and 2.13.0
Release Removed

2.12.0

-XdisableUpdateCheck and -XcheckForUpdates, -incrementalCompileWarnings, -Xlibraries, -XoutLibrary, -Xlibrary, -Xlink, -missingDepsFile, -overlappingSourceWarnings, XstrictResources and enforceStrictResources; the no-op main classes com.google.gwt.user.tools.ApplicationCreator and ProjectCreator; RequestFactoryJarExtractor is no longer in any release jar. -XfragmentMerge stays accepted but has no effect

2.13.0

com.google.gwt.dev.ApplicationCreator, com.google.gwt.dev.RunWebApp, com.google.gwt.dev.GetJreEmulation, SignatureDumper, the SpeedTracer classes (replaced by JFR), ArgHandlerOutDir and ArgHandlerFragmentMerge (so -XfragmentMerge itself is now an unknown option), com.google.gwt.dev.codeserver.RecompileListener. Deprecated for removal: the DashboardNotifier classes, RunStyleSelenium, ArgHandlerEnableGeneratorResultCaching

Browsers and the user.agent property

The user.agent values changed at every browser generation, and any deferred-binding rule or CSS condition that names an old value stops matching.

Table 6. Permutations over time
Release Values of user.agent

1.7.0

ie8 added (the first release with a breaking note for libraries that specialize by user agent)

2.6.0 (RC1)

ie6 (which also handled IE7) disabled by default, ie10 added; support for IE6 and IE7 "will be removed in the next major GWT release"

2.10.0

IE 8, 9 and 10 dropped. In 2.13.1 UserAgent.gwt.xml defines gecko1_8 and extends it with safari only; Chromium-based browsers and Edge use safari, IE11 maps to gecko1_8. The webApiUsage property (stable or modern, default modern) and user.agent.runtimeWarning exist

Migration recipes

Migrate in this order; every step leaves the project buildable, and the order puts the build first because every later step needs the 2.13 tools.

flowchart TD a["Legacy build"] --> b["1 Plugin: net.ltgt gwt-maven-plugin 1.3.0"] b --> c["2 Coordinates: org.gwtproject BOM"] c --> d["3 Servlets: javax to jakarta if the container needs it"] d --> e["4 Compiler: sourceLevel 17 and failOnError true"] e --> f{"Does the module build and start in Super Dev Mode?"} f -->|"no"| g["Fix module XML and source paths, see Pitfalls"] g --> e f -->|"yes"| h["5 Events and resources: handlers, ClientBundle, Scheduler"] h --> i["6 CSS to GSS, one folder at a time"] i --> j["7 JSNI to JsInterop, Elemental to Elemental2"] j --> k["8 Security review: SafeHtml, XSRF, CSP"] k --> l["Done: GWT 2.13.1 on a supported JDK"]

com.google.gwt to org.gwtproject

GWT’s Maven coordinates changed in 2.10.0, and only the coordinates changed. The Java packages (com.google.gwt.user.client.ui, com.google.gwt.core.client), the module names (com.google.gwt.user.User) and the *.gwt.xml files are exactly the same in 2.13.1, so no source file is touched by this step.

Table 7. Coordinates before and after
Before (up to 2.10.0) After (2.10.0 and later) Notes

com.google.gwt:gwt (BOM)

org.gwtproject:gwt

import with <type>pom</type> and <scope>import</scope>; 2.13.1 manages gwt-user, gwt-dev, gwt-codeserver, gwt-servlet, gwt-servlet-jakarta, requestfactory and jsinterop-annotations 2.0.0

com.google.gwt:gwt-user, gwt-dev, gwt-servlet, gwt-codeserver

org.gwtproject:gwt-user, gwt-dev, gwt-servlet, gwt-codeserver

versions 2.10.0 are published under both groupIds, 2.10.1 and later under org.gwtproject only

com.google.gwt:gwt-servlet (javax)

org.gwtproject:gwt-servlet-jakarta (Jakarta) or org.gwtproject:gwt-servlet (javax)

2.11.0 and later; see the next recipe

RequestFactory inside gwt-user

org.gwtproject.web.bindery:requestfactory-client, requestfactory-server, requestfactory-server-jakarta, requestfactory-apt

the groupId is org.gwtproject.web.bindery, not org.gwtproject; the annotation processor requestfactory-apt is mandatory

com.google.gwt:gwt-elemental

none (see the Elemental recipe)

last version 2.9.0; there is no org.gwtproject:gwt-elemental

com.google.jsinterop:jsinterop-annotations

same coordinates; the BOM pins 2.0.0, version 2.1.0 exists

split out of GWT in 2.8.0

The repository metadata confirms the cut: com.google.gwt:gwt-user and gwt-servlet have 2.10.0 as latest and release version (last updated 2022-06-23), and asking for a newer version under the old groupId fails like this:

Could not find artifact com.google.gwt:gwt-user:jar:2.13.1

The POM of that version does not exist in the old group on Maven Central (the request answers 404). The edit that fixes it is a groupId change plus a BOM:

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.gwtproject</groupId>
      <artifactId>gwt</artifactId>
      <version>2.13.1</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

<dependencies>
  <dependency>
    <groupId>org.gwtproject</groupId>
    <artifactId>gwt-user</artifactId> <!-- version from the BOM -->
  </dependency>
  <dependency>
    <groupId>org.gwtproject</groupId>
    <artifactId>gwt-dev</artifactId>
  </dependency>
</dependencies>

If a library you depend on still declares com.google.gwt:gwt-user 2.10.0 transitively, import the new BOM first so Maven resolves a single version, and exclude the old coordinates.

javax to jakarta

A servlet container that implements Jakarta Servlet 5 or later (Tomcat 10+, Jetty 11+, Spring Boot 3+) has no javax.servlet classes, so GWT’s server classes that extend javax.servlet.http.HttpServlet cannot load. GWT 2.11.0 added Jakarta variants; the client side is untouched.

Table 8. What moves and what stays
Stays the same Moves

com.google.gwt.user.client.rpc.RemoteService, AsyncCallback, @RemoteServiceRelativePath, XsrfProtectedService, XsrfToken, XsrfTokenService (client and shared code)

com.google.gwt.user.server.rpc.RemoteServiceServlet becomes com.google.gwt.user.server.rpc.jakarta.RemoteServiceServlet

Your DTOs and your service interfaces

XsrfProtectedServiceServlet and XsrfTokenServiceServlet become the classes of the same names in com.google.gwt.user.server.rpc.jakarta

The module XML

com.google.gwt.logging.server.RemoteLoggingServiceImpl becomes the class in com.google.gwt.logging.server.jakarta

*.gwt.xml, the host page

RequestFactory: com.google.web.bindery.requestfactory.server.RequestFactoryServlet becomes the class in com.google.web.bindery.requestfactory.server.jakarta, from org.gwtproject.web.bindery:requestfactory-server-jakarta

servlet-api provided by the container

the dependency org.gwtproject:gwt-servlet-jakarta (runtime), jakarta.servlet:jakarta.servlet-api 6.0.0 (provided) and the web.xml namespace https://jakarta.ee/xml/ns/jakartaee

The mismatch is easy to recognise because the compiler cannot even read the old servlet class against Jakarta Servlet 6. Compiling a servlet that still extends the javax base class with gwt-user 2.13.1 and jakarta.servlet-api 6.0.0 on the class path printed (JDK 21):

src/com/example/bookshelf/server/LegacyCatalogServlet.java:3: error: cannot access HttpServlet
public class LegacyCatalogServlet extends RemoteServiceServlet {
                                          ^
  class file for javax.servlet.http.HttpServlet not found
src/com/example/bookshelf/server/LegacyCatalogServlet.java:3: error: cannot access ServletException
public class LegacyCatalogServlet extends RemoteServiceServlet {
       ^
  class file for javax.servlet.ServletException not found
2 errors

Changing the import to the jakarta package, with gwt-servlet-jakarta on the class path, compiled cleanly. The reverse mistake (a Jakarta servlet class deployed to a javax container) fails when the container loads the class. Keep one flavour per deployment.

// Before: javax container
import com.google.gwt.user.server.rpc.XsrfProtectedServiceServlet;

// After: Jakarta container (Tomcat 10+, Jetty 11+, Spring Boot 3+)
import com.google.gwt.user.server.rpc.jakarta.XsrfProtectedServiceServlet;

Two related facts move with this recipe. The validation annotations follow the same split: a javax.validation constraint on a DTO is silently ignored by a Jakarta Bean Validation server and vice versa (see Validation). And on JDK 17 and later every reflectively serialized exception fails over GWT-RPC unless the container JVM is started with --add-opens java.base/java.lang=ALL-UNNAMED or the class has a custom field serializer (upstream issue gwtproject/gwt#9793; see GWT-RPC).

The Codehaus plugin to the net.ltgt plugin

org.codehaus.mojo:gwt-maven-plugin (last release 2.10.0, 2022-06-25) is tied to one GWT version and one project layout. net.ltgt.gwt.maven:gwt-maven-plugin 1.3.0 is independent of the GWT version, has the gwt-app and gwt-lib packagings, and is what the official Getting Started page and the archetype use. The detailed goal table and the migration order are in Build Tools: Maven & Gradle; this is the shortest working summary.

Table 9. Plugin differences that cause migration work
Codehaus (Mojo) plugin net.ltgt plugin

Compiles with its own GWT dependencies

The project declares gwt-dev and gwt-user itself (through the org.gwtproject:gwt BOM)

gwt:run, gwt:run-codeserver, gwt:debug, gwt:generateAsync, gwt:i18n, gwt:css, gwt:mergewebxml, gwt:eclipse

Only gwt:compile, gwt:codeserver and (partly) gwt:devmode have equivalents; the others are gone, so write what they generated

Dozens of <configuration> parameters

Few properties plus list properties: compilerArgs, codeserverArgs, devmodeArgs, testArgs, jvmArgs; a flag the old plugin exposed as a parameter becomes an <arg>

One module holds the application

Modules -shared, -client (gwt-app), -server (war); gwt:codeserver runs from the root POM

The descriptor is wherever it is

src/main/module.gwt.xml by default; set skipModule to true to keep a hand-written descriptor

Goal test mimics Surefire

gwt:test needs <includes> (or -Dtest) or it runs no tests

The command-line wildcard form -pl '*-client' that appears in several guides does not work with Maven 3.9: it fails with Could not find the selected project in the reactor: *-client. Name the project (-pl bookshelf-client or -pl :bookshelf-client). Wildcards are a Maven 4 feature.

JSNI to JsInterop

JSNI (/*-{ ... }-*/ bodies of native methods and JavaScriptObject overlays) still compiles in 2.13.1, but JsInterop (stable since 2.8.0, compatible with J2CL since 2.9.0) replaces it for new code and is the only style that carries over to J2CL. The mapping, verified by compiling both versions, is in JSNI & Overlay Types and JsInterop; the short version:

Table 10. JSNI constructs and what replaces them
JSNI or overlay JsInterop

A JavaScriptObject subclass with final native getters

A @JsType(isNative = true) class with @JsProperty members and @JsOverlay methods

$wnd.Intl.NumberFormat(locale).format(n) in a native method body

A native type @JsType(isNative = true, namespace = "Intl", name = "NumberFormat") with public native String format(double value)

$entry(...) and $wnd.name = ... to publish Java

@JsType(namespace = "bookshelf", name = "Api") or @JsMethod on a Java class, compiled with -generateJsInteropExports

JSON.parse through a native method

@JsMethod(namespace = JsPackage.GLOBAL, name = "JSON.parse") or Elemental2’s Global.JSON

Callbacks as JavaScript functions

A @JsFunction interface

Rules that tripped the lab builds: the export flag -generateJsInteropExports is needed in compilerArgs and (for Super Dev Mode) in codeserverArgs; the filters -includeJsInteropExports and -excludeJsInteropExports take Java regular expressions even though the 2.8.1 notes call them wildcards; of the newer annotations only @JsIgnore and @JsOptional are acted on by the 2.13.1 compiler (@JsNullable, @JsNonNull, @JsAsync and @JsEnum compile but do nothing).

Elemental to Elemental2

The first Elemental library (announced as experimental in 2.5, generated from WebKit IDL) was deprecated in 2.9.0 and its source is not in the 2.13.1 tree; the last artifact is com.google.gwt:gwt-elemental 2.9.0. Elemental2 (com.google.elemental2:elemental2-dom, latest stable 1.3.2; 1.4.0-RC1 is a pre-release; it is not managed by the GWT BOM, so declare its version) is a set of JsInterop native types generated from the Closure externs and works in GWT 2 and J2CL.

Table 11. Elemental and Elemental2
Elemental (1) Elemental2

Browser.getWindow(), Browser.getDocument()

DomGlobal.window, DomGlobal.document

window.newXxx() factories

The constructors (new WebSocket(url))

Elemental’s own collections and elemental.json

JsArray, JsMap, JsSet (elemental2-core), Js from jsinterop-base, Global.JSON

Vendor-prefixed WebKit APIs

The standard names

One Elemental2 behaviour matters during a port: Promise.all with a String type argument throws a ClassCastException when the promises resolve to strings; declare the element type Object. See DOM & Elemental2 for the complete mapping.

CSS to GSS

Legacy CssResource syntax (@def, @eval, @sprite, @if user.agent) has been deprecated since 2.8.0, but it is still the default in 2.13.1: CssResource.enableGss is false, CssResource.conversionMode is off and CssResource.gssDefaultInUiBinder is false. Automatic conversion is a bridge that the compiler says "will be removed in the next version of GWT".

The sequence that worked on the Bookshelf (details, converter output and every combination of the three properties are in Styling: CSS & GSS):

  1. Turn on CssResource.enableGss and set CssResource.conversionMode to strict, so remaining .css files are converted in memory.

  2. Convert a folder with com.google.gwt.resources.converter.Css2Gss (its class path needs gwt-dev as well as gwt-user), review the .gss it wrote, fix what it dropped (comments, CSS hacks).

  3. Keep @Source("book.css") as it is: with enableGss true the compiler prefers a .gss file of the same base name.

  4. When no .css file is referenced, delete them, remove conversionMode and set gssDefaultInUiBinder to true.

<!-- bookshelf App.gwt.xml: the bridge configuration -->
<set-configuration-property name="CssResource.enableGss" value="true" />
<set-configuration-property name="CssResource.conversionMode" value="strict" />
<!-- the end state: enableGss true, gssDefaultInUiBinder true, no conversionMode -->

There is no GssResource type in 2.13.1: GSS is a syntax of CssResource selected by the property (the generator is GssResourceGenerator). DataGrid, CellTable and the other widgets that embed legacy CSS need strict conversion or gssDefaultInUiBinder once enableGss is true.

Smaller replacements in code

Most of the rest of a 1.x to 2.x port is mechanical. Each snippet is the current form; the old form is named in the table in the next section.

// listeners to handlers
Button borrow = new Button(messages.borrow());
HandlerRegistration registration = borrow.addClickHandler(event -> presenter.borrow(book.getId()));
// later: registration.removeHandler();

// DeferredCommand to Scheduler
Scheduler.get().scheduleDeferred(() -> grid.setFocus(true));

// ServiceDefTarget.setServiceEntryPoint to an annotation on the interface
@RemoteServiceRelativePath("catalog")
public interface CatalogService extends XsrfProtectedService { /* ... */ }

Outdated in older material, row by row

The table below keeps, in one place, every statement of the 2007 first edition (GWT 1.3 and 1.4) that is outdated, with the current form. The book’s concepts (RPC, widgets, deferred binding, JSNI) are still the right ideas; their APIs, tools and build steps are not. The same rows are repeated, with more detail, on the page named in the last column. The Developer Guide and tutorials of gwtproject.org are in most places accurate descriptions of the code, but some pages predate Java 8 and still show the listener era, JSNI or classic Dev Mode.

Table 12. Platform, build and tooling
Area Older material Current practice Page

Platform

GWT 1.3/1.4, Java 1.4 client code (no generics, enums, annotations), JUnit 3

GWT 2.13.1, Java 17 source level (-sourceLevel 17), JUnit 4 style GWTTestCase

Compiler & Compilation

Coordinates

SDK zip with platform-specific gwt-dev-*.jar

Maven Central, org.gwtproject BOM

Build Tools

Project creation

projectCreator, applicationCreator, junitCreator

The modular-webapp Maven archetype; webAppCreator is deprecated since 2.11, the 1.x creators are gone

Getting Started

Dev loop

Hosted mode (GWTShell, whitelist and blacklist, -noserver), "Debug As Java Application"

Super Dev Mode (gwt:codeserver), source maps in the browser devtools, a separate server (jetty:run or Spring Boot)

Development Mode & Debugging

Compiler

GWTCompiler -out

com.google.gwt.dev.Compiler -war, -optimize, -draftCompile, -sourceLevel, -generateJsInteropExports; source maps on by default since 2.12.0

Compiler & Compilation

Build

Ant build.xml, Eclipse .launch files

Maven (gwt-app and gwt-lib packagings) or a community Gradle plugin

Build Tools

Logging

GWT.log and Window.alert only

java.util.logging emulation (com.google.gwt.logging.Logging) and remote logging

Logging

Browsers

ie6, opera, gecko permutations, IE6 PNG filter hacks

gecko1_8 and safari only

Deferred Binding & Generators

Bootstrap

gwt.js and the gwt:module meta tag, *.cache.html, nocache-xs.js, std and xs linkers

<module>.nocache.js with the xsiframe linker; std and xs deprecated since 2.7.0

Linkers & Bootstrap

Table 13. Client code
Area Older material Current practice Page

Collections in RPC

The @gwt.typeArgs Javadoc annotation

Generics

GWT-RPC

Events

Listener interfaces (ClickListener, KeyboardListener, ChangeListener, TableListener, FormHandler, WindowResizeListener, EventPreview, Sources*Events), deprecated in 1.6

Handlers (ClickHandler, HandlerRegistration, Event.addNativePreviewHandler, Window.addResizeHandler); the listener classes still exist in 2.13.1 as deprecated types

Events & Handlers

Images

ImageBundle with @gwt.resource

ClientBundle and ImageResource with @Source

ClientBundle & Images

Layout

Table-based panels for page layout, HorizontalSplitPanel, VerticalSplitPanel

Layout panels (RootLayoutPanel, DockLayoutPanel, SplitLayoutPanel), CSS layout and UiBinder

Panels & Layout

Deferred logic

DeferredCommand, IncrementalCommand

Scheduler (scheduleDeferred, scheduleIncremental, scheduleFinally)

Delayed Logic & Scheduler

DOM

Static DOM.* element helpers

com.google.gwt.dom.client.* (the Document, Element and Style types) and Elemental2

DOM & Elemental2

JavaScript interop

JSNI and JavaScriptObject overlays

JsInterop (@JsType, @JsMethod, @JsProperty, @JsFunction, @JsOverlay)

JsInterop

Generators

Generators driven by Javadoc metadata

Annotations; generators are discouraged because J2CL does not support them, annotation processors are preferred

Deferred Binding & Generators

Styling

Legacy CssResource syntax is the book-era default

GSS, opt-in with CssResource.enableGss

Styling: CSS & GSS

History

A hidden history iframe

Hash-change events; there is no history iframe in 2.13.1

History & Navigation

Table 14. Data, server and communication
Area Older material Current practice Page

JSON

The lenient JSONParser.parse

JSONParser.parseStrict, JsonUtils.safeEval (it calls JSON.parse in 2.13.1) or JSON.parse through JsInterop and Elemental2

RequestBuilder, JSON & XML

RPC entry point

ServiceDefTarget.setServiceEntryPoint with GWT.getModuleBaseURL()

@RemoteServiceRelativePath; gwt-servlet-jakarta on Jakarta containers

GWT-RPC

Server push

Blocking Thread.sleep loops in servlets

WebSockets or Server-Sent Events through JsInterop and Elemental2, or an asynchronous servlet

Client-Server Communication

External services

Google AJAX Search, Google Video Search, Yahoo Search V1, Flash embedding

All are gone; examples in this section use the scenario’s own APIs

REST & JSON Libraries

Concepts the book lacks

Handlers, generics in RPC, @RemoteServiceRelativePath, UiBinder, ClientBundle/GSS, layout panels, cell widgets, editors, MVP with Activities and Places, EventBus, RequestFactory and AutoBeans, SafeHtml, RPC XSRF protection, code splitting, java.util.logging, JSR-303 validation, HTML5, ARIA, plural forms, Super Dev Mode, JsInterop, Elemental2, Java 8 to 17, Jakarta servlets, modular Maven projects, J2CL

Each has a page in this section; the index of this section lists them in reading order

Introduction & Architecture

The second edition of the book (2013) has a Manning page that resolves, but it was not consulted for this section.

Errata and unsafe practices: what to do instead

Several older books, tutorials and sample projects (the first edition among them) contain practices that were never safe, and some code that never compiled. This section does not repeat them. It lists the topics and the correct current practice, with the page that explains it.

Table 15. Topic and the practice to use
Topic Correct current practice Page

Credentials in examples and client code

Use placeholders in every example. Keep credentials and keys on the server and out of client sources and of RPC payloads; send secrets only over TLS and verify every request on the server

XSRF, RPC & Server Security

Markup built from user data or URLs

Treat user data as text (setText) and build markup with SafeHtml, SafeHtmlTemplates, SafeUri and UriUtils; never turn user input into markup by concatenation

SafeHtml & XSS

Opening URLs taken from remote data

Validate scheme and host with UriUtils and allow only http and https before navigating or setting an anchor target

SafeHtml & XSS

Parsing third-party JSON

Use strict parsing (parseStrict, JSON.parse); validate the shape before use

RequestBuilder, JSON & XML

Proxy and upload servlets

Authenticate and authorize the caller, bound the request size and type, choose the stored file name yourself, and never swallow exceptions

Server Integration & Deployment

Emulated server push

Do not hold a container thread per client; use WebSockets, Server-Sent Events or an asynchronous servlet

Client-Server Communication

Cross-site request forgery on RPC and other state-changing endpoints

Protect RPC with XsrfProtectedService and XsrfTokenServiceServlet, and other endpoints with the framework’s token (a double-submit cookie, for example); XSRF tokens here are stateless

XSRF, RPC & Server Security

Content Security Policy

Pick a linker and output style that fit the policy; measured combinations are on SafeHtml & XSS and XSRF, RPC & Server Security

Linkers & Bootstrap

Code that does not compile and typos in API names

Take class and method names only from the Javadoc of the version you build against; a Java keyword as a parameter name or a non-void method with an empty body is an error in any release

Getting Started

GWT’s own security history

Old XSS problems were in generated or bundled GWT code (2.4 and 2.5, the GWTTestCase files fixed in 2.5.1); the fix is to rebuild with a fixed GWT. No CVE against GWT 2.6 or later was found in the NVD on 2026-10-08

SafeHtml & XSS

Corrections and deviations

While this section was being written every claim was checked against the 2.13.1 sources, the release notes and the live pages. Where a statement of the first plan, of an official page or of an earlier draft of this section differed from what the code does, the difference is recorded here so that you can trust the topic pages over the older text.

Table 16. Platform and tooling
Statement What 2.13.1 shows

"`-sourceLevel` defaults to the level of the running JDK" (the first reading of SourceLevel.DEFAULT_SOURCE_LEVEL)

The command-line compiler’s default is 1.8 (the default argument registered by ToolBase), which the -help text and the Developer Guide say. auto resolves to the level of the running JVM, and the gwt-maven-plugin <sourceLevel> default comes from maven.compiler.source. Java 12 to 17 syntax needs an explicit -sourceLevel 17, and the Developer Guide’s list [auto, 1.8, 9, 10, 11, 17] is accurate

-failOnError has an alias -strict

Confirmed: ArgHandlerStrict adds -strict; the 2.13.0 notes say "Support -strict in test arguments". Default off in the CLI; the archetype sets failOnError true

SDM became the default in "2.7"

Confirmed as 2.7.0 RC1 (2014-10-30): "Super Dev Mode is now the default". 2.6.0 RC4 had turned the hook on by default

The Developer Guide DevMode options (-[no]startServer, -port 8888) describe the server

They exist, but the 2.13.0 notes say the DevMode server serves static files only by default and the Jetty launcher is "due to be removed". The Developer Guide page does not say so

<collapse-all-properties/>, CssResource.obfuscationPrefix and jre.checks.* (flagged "from knowledge")

Verified in the sources: ModuleDefSchema, Resources.gwt.xml and Preconditions.gwt.xml (jre.checks.checkLevel NORMAL, OPTIMIZED or MINIMAL; -XcheckCasts is deprecated in favour of it)

-XfragmentMerge "does nothing"

The 2.12.0 notes say it has no effect; in 2.13.0 its argument handler was removed, so 2.13.1 rejects it as an unknown option and prints the usage. Use -XfragmentCount

-localWorkers starts parallel workers

In-process permutation threads are capped by the system property gwt.jjs.maxThreads (default 1); additional workers are separate JVMs

-pl '*-client'

Rejected by Maven 3.9.16 (Could not find the selected project in the reactor: *-client); wildcards belong to Maven 4. The official IntelliJ page and the archetype README still show the wildcard

The gwt-maven-plugin usage page

It still shows the BOM at 2.13.0 while the plugin is 1.3.0

Gradle

There is no official Gradle plugin or documentation page; org.docstr.gwt 2.2.9 and de.esoco.gwt 1.3.1 are community plugins

RequestFactory is in "maintenance mode"

Not confirmed by any official source. The 2.13.1 BOM still publishes it (groupId org.gwtproject.web.bindery), and the Developer Guide has no deprecation note. This section recommends alternatives as an opinion only

Table 17. Links, URLs and libraries
Statement What was found

DevGuideJsInterop.html and DevGuideDevMode.html

Both answer 404; the JsInterop page is DevGuideCodingBasicsJsInterop.html. https://www.gwtproject.org/articles.html, https://www.gwtproject.org/tutorials/ and the Open Collective slug gwt also answer 404 (use articles/articles.html, the tutorial pages linked from every page’s sidebar, and the Open Collective project slug gwt-project)

The JSNI restriction page

It lives at doc/latest/gwt-dev-help/longJsniRestriction.html; without /doc/latest it is 404

The Gitter room, GWT Material and GIN URLs of the first plan

GWT Material is https://github.com/GwtMaterialDesign/gwt-material; GIN is https://github.com/google/gin (archived 2014; gwtproject/gwt-gin does not exist); the Gitter room redirects to app.gitter.im

Nalu is com.github.nalukit 2.20.6

Current group id is io.github.nalukit (Nalu 4.0.2, 2026-02-12)

RestyGWT 1.4 (2013)

Central has releases up to 2.2.7 (2020); it needs jaxb-api on JDK 21. AutoREST 0.11 (2023) is on Central as com.intendia.gwt.autorest

GIN works with GWT 2.13

GIN 2.0.0 does not run on JDK 21 (Guice 3 fails with InaccessibleObjectException). Dagger 2.60.1 (dagger, dagger-gwt, dagger-compiler, module dagger.Dagger) works with GWT 2.13.1

J2CL is "alpha"

The J2CL README says both that the project is an alpha developer preview, not an official Google product, and that Google uses it in production. There is no GWT 3 release and the org.gwtproject.* ports are release candidates

CVE-2012-5920 is fixed in 2.5.1

NVD lists 2.4 through 2.5 Final as affected; the 2.5.1 RC1 notes name only the GWTTestCase files (CVE-2013-4204)

Table 18. Client and build behaviour found by running the examples
Statement What was found

@UiRenderer is an annotation

UiRenderer is an interface; {book.title} in UiBinder calls title(), not getTitle()

The modules of the Developer Guide validation sample work on JDK 21

Client validation is deprecated since 2.8.0 and on JDK 21 needs -Dgwt.validation.ignoreXml=true or fails with NoClassDefFoundError for javax/xml/bind/JAXBException

The Developer Guide CompositeExample compiles

It does not (a missing ClickEvent import and a deprecated setChecked)

Disabled log calls are removed from the compiled output

In 2.13.1 only the handlers, popup and RPC proxy compile out; a disabled log call is not removed

The compiler reports every error

Without -failOnError the compiler hides JSNI and overlay errors ("Ignored N units with compilation errors in first pass")

script-src 'self' is enough for a CSP-clean page

With the default obfuscated output the xsiframe linker installs code through script.text, so script-src 'self' alone fails; -style PRETTY, the direct-install linker or the single-script linker work. A nonce alone fails, a nonce with 'strict-dynamic' works; default-src 'self' blocks StyleInjector

JsInterop filters are wildcards

They are Java regular expressions in 2.13.1 (the 2.8.1 notes say wildcards)

Deferred binding has property-fallback-value

No such element; use the fallback-value attribute or set-property-fallback. <none> is a NOR in source and the last declared rule is examined first

RPC works the same on every JDK

On Java 17 and later every reflectively serialized exception, IncompatibleRemoteServiceException included, needs --add-opens or a custom field serializer; records need a custom field serializer; protocol version 7 is evaluated with eval (a CSP needs unsafe-eval or -Dgwt.rpc.version=8)

A Spring Boot executable jar serves the module directory

Not from BOOT-INF/classes/META-INF/resources: the ServletContext cannot see it and the serialization policy is "not found"; package the client output as META-INF/resources of a separate jar

Symbol maps ship in the war

They are written under target/gwt/deploy, not in the war

The std and xs linkers, AsyncProxy, Prefetcher and sso behave as in older material

std and xs are deprecated since 2.7.0, AsyncProxy is absent from 2.13.1, Prefetcher is a no-op in development mode and the sso linker fails when the code has split points

Worked example: migrating the Bookshelf

The scenario of this section is a book catalogue. Suppose its first version was written for GWT 2.8 on Tomcat 8: the Codehaus plugin, com.google.gwt coordinates, a javax servlet and one JSNI method to format a number with the browser’s Intl. This is the migration, step by step. The "after" files are the files of the scratch application that passed mvn verify (nine tests) on GWT 2.13.1 and JDK 21.

Step 1: POM and plugin

<!-- before -->
<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>gwt-maven-plugin</artifactId>
  <version>2.8.2</version>
</plugin>
<dependency>
  <groupId>com.google.gwt</groupId>
  <artifactId>gwt-user</artifactId>
  <version>2.8.2</version>
</dependency>
<!-- after: parent POM -->
<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.gwtproject</groupId>
      <artifactId>gwt</artifactId>
      <version>2.13.1</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
    <dependency>
      <groupId>jakarta.servlet</groupId>
      <artifactId>jakarta.servlet-api</artifactId>
      <version>6.0.0</version>
    </dependency>
  </dependencies>
</dependencyManagement>

<build>
  <pluginManagement>
    <plugins>
      <plugin>
        <groupId>net.ltgt.gwt.maven</groupId>
        <artifactId>gwt-maven-plugin</artifactId>
        <version>1.3.0</version>
        <extensions>true</extensions>
        <configuration>
          <sourceLevel>17</sourceLevel>
          <failOnError>true</failOnError>
        </configuration>
      </plugin>
    </plugins>
  </pluginManagement>
</build>

The client module uses <packaging>gwt-app</packaging>, declares gwt-user and gwt-dev without versions, and passes -generateJsInteropExports in compilerArgs.

Step 2: the servlet

package com.example.bookshelf.server;

import com.example.bookshelf.shared.Book;
import com.example.bookshelf.shared.BookNotFoundException;
import com.example.bookshelf.shared.BookPage;
import com.example.bookshelf.shared.CatalogService;
import com.google.gwt.user.server.rpc.jakarta.XsrfProtectedServiceServlet;

public class CatalogServiceImpl extends XsrfProtectedServiceServlet implements CatalogService {
  @Override
  public BookPage getBooks(int start, int length) {
    return CatalogRepository.INSTANCE.page(start, Math.min(length, 100));
  }

  @Override
  public Book saveBook(Book book) throws BookNotFoundException {
    if (book.getTitle() == null || book.getTitle().isBlank() || book.getTitle().length() > 200) {
      throw new IllegalArgumentException("Invalid title");
    }
    return CatalogRepository.INSTANCE.save(book);
  }

  // getBook(long id) omitted
}

The import is the only difference from the javax version; the server also validates its input, because nothing the browser sends can be trusted. web.xml moves to the https://jakarta.ee/xml/ns/jakartaee namespace (version 5.0), declares gwt.xsrf.session_cookie_name and maps XsrfTokenServiceServlet (the jakarta class) next to the service servlet.

Step 3: the JSNI method

// before: JSNI in a widget, legacy but still compiles in 2.13.1
// private static native String format(String locale, double n) /*-{ ... }-*/;
// ("..." is the native body that called the browser's Intl.NumberFormat)
// after: a native JsInterop type, no JavaScript text
package com.example.bookshelf.client.interop;

import jsinterop.annotations.JsType;

@JsType(isNative = true, namespace = "Intl", name = "NumberFormat")
public class NumberFormatJs {
  public NumberFormatJs(String locale) {}

  public native String format(double value);
}

Used as new NumberFormatJs("es").format(1234.5). Exporting the same logic to the host page is one more annotation, and needs the compiler flag:

@JsType(namespace = "bookshelf", name = "Api")
public final class ExportedApi {
  private ExportedApi() {}

  @JsMethod
  public static String formatCopies(String locale, double n) { return new NumberFormatJs(locale).format(n); }
}

In the browser bookshelf.Api.formatCopies('es', 1234.5) returned "1234,5" (no grouping separator for four digits with the es locale). Without -generateJsInteropExports in both compilerArgs and codeserverArgs the call fails with ReferenceError: bookshelf is not defined.

Step 4: module XML and styling

<module>
  <inherits name="com.google.gwt.user.User" />
  <inherits name="com.google.gwt.user.theme.clean.Clean" />
  <inherits name="com.google.gwt.i18n.I18N" />
  <inherits name="com.google.gwt.place.Place" />
  <inherits name="com.google.gwt.activity.Activity" />
  <inherits name="com.google.gwt.editor.Editor" />

  <source path="client" />
  <source path="shared" />

  <entry-point class="com.example.bookshelf.client.App" />

  <extend-property name="locale" values="en" />
  <extend-property name="locale" values="es" />
  <set-configuration-property name="CssResource.enableGss" value="true" />
  <set-configuration-property name="CssResource.conversionMode" value="strict" />
</module>

The module names are unchanged from GWT 2.8, which is why this step usually needs no edit other than the two GSS properties. The module file moves to src/main/module.gwt.xml (or the plugin is told skipModule).

Step 5: run and check

mvn -B verify                       # build everything, run the 9 tests
mvn -B gwt:codeserver -pl bookshelf-client -am   # Super Dev Mode on http://127.0.0.1:9876/

The code server printed its ready line (ready at http://127.0.0.1:9876/) with the embedded Jetty 9.4.58; -pl '*-client' would have failed on Maven 3.9, as noted above. Run the server module separately, for example with jetty-ee10-maven-plugin 12.1.10 and -Djetty.http.port=8081.

Pitfalls

The messages below were printed during the Bookshelf work on 2.13.1 with JDK 21 (a few from JDK 26 with the same build).

Table 19. Migration failures and their fixes
Symptom (as printed) Cause Fix

Could not find artifact com.google.gwt:gwt-user:jar:2.13.1

2.13.1 is not published under the old groupId; com.google.gwt stops at 2.10.0

Change the groupId to org.gwtproject and import the BOM

error: cannot access HttpServlet and class file for javax.servlet.http.HttpServlet not found

A servlet extends the javax GWT class while the project has Jakarta Servlet 6

Import com.google.gwt.user.server.rpc.jakarta.* and depend on gwt-servlet-jakarta

Could not find the selected project in the reactor: *-client

A wildcard -pl argument on Maven 3.9

-pl bookshelf-client or -pl :bookshelf-client

Unable to find 'com/example/bookshelf/widgets/Widgets.gwt.xml' on your classpath; could be a typo, or maybe you forgot to include a classpath entry for source?

skipModule is true but there is no descriptor in the library’s target/classes

Keep the descriptor at src/main/module.gwt.xml or ship the hand-written one as a resource

No source code is available for type com.example.bookshelf.shared.Book; did you forget to inherit a required module?

The sources classifier jar of the shared module is only produced at package

Run mvn verify or install, not mvn test -pl ... -am

The following non-obfuscated class is present in a strict CssResource: low-stock. Fix by adding String accessor method(s) ...

A dashed class name has no accessor; the accessor lowStock() binds to .lowStock

Add an accessor, or declare the name with @external

Your ClientBundle is referencing css files instead of gss. You will need to either convert these files to gss using the converter tool or turn on auto convertion in your gwt.xml file. ...

CssResource.enableGss is true and conversionMode is off, and widgets such as DataGrid embed legacy CSS

CssResource.conversionMode = strict, or gssDefaultInUiBinder = true

Only either css files or gss files are supported on one interface

A @Source list mixes .css and .gss files

Convert every file of the list, or none

Ignored 1 unit with compilation errors in first pass.

failOnError is off, so the compiler hides the other errors

Set <failOnError>true</failOnError> or pass -strict

java.lang.reflect.InaccessibleObjectException: Unable to make field private java.lang.String java.lang.Throwable.detailMessage accessible: module java.base does not "opens java.lang" to unnamed module

A server-side exception serialized by GWT-RPC on Java 17 or later (gwtproject/gwt#9793)

Start the container JVM with --add-opens java.base/java.lang=ALL-UNNAMED or add a custom field serializer

//EX[2,1,["com.google.gwt.user.client.rpc.RpcTokenException/2345075298","Invalid RPC token (XSRF token missing)"],0,7]

An XSRF-protected call without the token (this reply appears once the --add-opens issue is fixed)

Fetch the token from XsrfTokenServiceServlet first and set it on the service with setRpcToken

NoClassDefFoundError for javax/xml/bind/JAXBException

Client-side validation on JDK 21 without gwt.validation.ignoreXml

Pass -Dgwt.validation.ignoreXml=true to the compile, test and code-server JVMs as each goal requires

[WARN] Plural form 'one' unknown in com.google.gwt.i18n.client.impl.plurals.DefaultRule: ignoring

Messages with plurals but no locale file for en, so the default rule applies

Add an (even empty) AppMessages_en.properties

ReferenceError: code is not defined, gwt:onLoadErrorFn not called

Obfuscated default output with a missing permutation

Check that the permutation file was deployed next to the nocache.js file

in {msg.title}, no field named msg: <g:Label text='{msg.title}'>

A UiBinder {msg.x} expression without a ui:with field

Declare <ui:with field="msg" type="..."/>

A blank screen and no error

A DockLayoutPanel inside a plain SimplePanel (zero height)

Use SimpleLayoutPanel or ResizeComposite as the container

A migration checklist

  1. Pin the toolchain: JDK 21 (the tools need Java 11 or later), Maven 3.9, GWT 2.13.1, gwt-maven-plugin 1.3.0.

  2. Replace the plugin and the groupId, import the org.gwtproject:gwt BOM and delete explicit GWT versions.

  3. Set sourceLevel to 17 and failOnError to true, and fix the new errors one at a time.

  4. Switch servlets to jakarta if the container requires it, and set --add-opens java.base/java.lang=ALL-UNNAMED for exception serialization on Java 17 and later.

  5. Run Super Dev Mode with gwt:codeserver from the root POM; run the server separately.

  6. Replace listener interfaces, ImageBundle, DeferredCommand and DOM.* calls with their current forms; the compiler’s deprecation warnings list them.

  7. Convert CSS to GSS folder by folder with strict conversion as the bridge.

  8. Convert JSNI to JsInterop, Elemental to Elemental2; add the export flag to both compilerArgs and codeserverArgs.

  9. Review String.split, Collectors.toMap and AccessControlException uses for the 2.13.0 changes.

  10. Review security: user data as text, SafeHtml for markup, XSRF protection, a CSP that matches the chosen linker and output style.

  11. Run mvn verify and a manual Super Dev Mode session before moving on to J2CL-oriented clean-ups.

The topic pages quoted above give the detail: Build Tools: Maven & Gradle, Compiler & Compilation, JsInterop, Styling: CSS & GSS, SafeHtml & XSS and XSRF, RPC & Server Security. The landing page of this section lists all pages in reading order and holds the bibliography, and the cheat sheet condenses the flags and coordinates into a one-page PDF.