Development Mode & Debugging
|
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, gwt-maven-plugin 1.3.0 (net.ltgt.gwt.maven), a JDK 21 toolchain with -sourceLevel 17
and Jakarta Servlet 6 on the server side (Jetty 12 EE 10), and was checked on 2026-10-08; the code server and DevMode runs
shown here were executed on that stack with the Bookshelf scratch application. It is about build and tooling code, the
compiler process you keep running while you write client code, and how it cooperates with your server code. The
application sources themselves are unchanged by anything below, except for the optional GWT.log and GWT.debugger calls in
the debugging section.
The development loop at a glance
A GWT application is Java that is compiled to JavaScript, so there are two questions during development: how do you see a change without a full production compile, and how do you debug code that the browser runs as JavaScript. Since GWT 2.7 the answer to both is Super Dev Mode (SDM):
-
a separate Java process, the code server, compiles your modules on demand in draft mode and serves the result;
-
the browser loads that output instead of the deployed output, and you debug it in the browser devtools through source maps that point back to your
.javafiles; -
your own server (Jetty, Tomcat, Spring Boot) serves the host page and the RPC or REST endpoints exactly as in production.
The same pieces exist under several names, and the official documentation still mixes them:
| Tool | What it is | Status |
|---|---|---|
|
The Super Dev Mode compiler and web server, a plain Java program. |
The recommended tool. This is what the rest of the page is about. |
|
A Swing window plus an optional embedded web server that starts the code server for you ( |
Still shipped. Since 2.13.0 its embedded server only serves static files, and using it as an application server is deprecated. |
Classic Dev Mode (browser plugin, |
Ran the Java bytecode in the JVM and drove the browser through a plugin. |
Deprecated in 2.8.0, history only (see below). |
Hosted mode ( |
The name of classic Dev Mode in the early GWT versions. |
Gone. The official FAQ still carries a note that "Hosted mode" and "web mode" were renamed development mode and production mode. |
How Super Dev Mode works
The code server is an ordinary Java program with an embedded Jetty 9.4 web server (the GWT 2.13.1 BOM manages 9.4.58). It does not run your client code in the JVM: it compiles the whole module to JavaScript, as the production compiler does, but in draft mode with most optimizations off. That is why the core guarantee of old Dev Mode, "the Java ran the same as the JavaScript", is replaced by a simpler one: what you debug is the compiled JavaScript, shown to you as Java.
Reading the diagram from the top: the page asks the host server for the module’s bookshelf.nocache.js. The -launcherDir
output directory holds a small stub in that place, so the request reaches the code server, which recompiles if any source
changed and answers with the real bootstrap script. Without a -launcherDir you do the same by hand with the bookmarklets
(next section). When a compile fails, the code server logs the errors and continues to serve the previous version.
The article states the same thing from the other side: Super Dev Mode "replaces the internals of Dev Mode" and, because it
needs no plugin, works in modern browsers and on mobile browsers. It requires the xsiframe linker, which has been the
default since GWT 2.7, so a current module needs no configuration for it.
Starting the code server
With Maven
With gwt-maven-plugin the goal is gwt:codeserver. It is an aggregator goal: according to the plugin documentation, its
configuration lives in the root POM, not in the gwt-app module, and it runs the code server for the gwt-app modules of
the reactor. The modular-webapp archetype used by the Bookshelf scratch application generates this configuration in the
root POM:
<plugin>
<groupId>net.ltgt.gwt.maven</groupId>
<artifactId>gwt-maven-plugin</artifactId>
<inherited>false</inherited>
<configuration>
<launcherDir>${basedir}/bookshelf-server/target/gwt/launcherDir</launcherDir>
<!-- To be able to use gwt:devmode (useful on Windows where Ctrl+C won't kill gwt:codeserver)-->
<warDir>${basedir}/bookshelf-server/target/gwt/launcherDir</warDir>
<devmodeArgs>
<arg>-noserver</arg>
</devmodeArgs>
</configuration>
</plugin>
Three details are worth knowing. The goal puts the sources of the reactor modules that you depend on as gwt-lib or with the
sources classifier on the code server’s source path as they are, so an edit in bookshelf-shared is picked up without
rebuilding it. Dependencies use the runtime scope by default (classpathScope), where gwt:compile uses compile. And because
the code server takes different arguments from the compiler, an option that both need, such as a custom
-setProperty, has to be given twice, in compilerArgs for the production compile and in codeserverArgs for the code server.
The plugin documentation recommends limiting the reactor to client modules so that the server is not built on every start:
mvn gwt:codeserver -pl bookshelf-client -am
The real output of this command on the scratch application (JDK 21, GWT 2.13.1, plugin 1.3.0; the middle of the Maven log is omitted):
[INFO] --- gwt:1.3.0:codeserver (default-cli) @ bookshelf ---
[INFO] Turning off precompile in incremental mode.
[INFO] Super Dev Mode starting up
[INFO] workDir: .../app/target/gwt/codeserver
[INFO] Loading Java files in com.example.bookshelf.App.
[INFO] Module setup completed in 1651 ms
[WARNING] ...:INFO:oejs.Server:main: jetty-9.4.58.v20250814; ...
[WARNING] ...:INFO:oejs.AbstractConnector:main: Started ServerConnector@...{HTTP/1.1, (http/1.1)}{127.0.0.1:9876}
[INFO] The code server is ready at http://127.0.0.1:9876/
The [WARNING] prefix on the Jetty lines is only the Maven plugin forwarding the forked process’s standard error; they are
informational. The code server turns off -precompile itself ("Turning off precompile in incremental mode", printed by its
Options class) because an incremental compile works on one permutation, as explained below.
The same goal has launcherDir, logLevel, style, sourceLevel, failOnError, modules, projects, jvmArgs and
codeserverArgs parameters. On the scratch application, codeserverArgs containing -port 9886 was placed in the
client module’s POM and had no effect (the server still started on 9876) because the aggregator goal reads its
configuration from the root POM, so put any port change there.
Without Maven
Run com.google.gwt.dev.codeserver.CodeServer from gwt-codeserver with gwt-dev and the application classpath, giving at
least one module name. This is the 2.13.1 argument list as printed by the class itself:
CodeServer [-[no]allowMissingSrc] [-[no]compileTest] [-compileTestRecompiles count] [-[no]failOnError]
[-[no]precompile] [-port port] [-src dir] [-workDir dir] [-launcherDir]
[-bindAddress host-name-or-address] [-style (DETAILED|OBFUSCATED|PRETTY)]
[-setProperty name=value,value...] [-[no]incremental]
[-sourceLevel [auto, 1.8, 9, 10, 11, 17]]
[-logLevel (ERROR|WARN|INFO|TRACE|DEBUG|SPAM|ALL)] [-[no]generateJsInteropExports]
[-includeJsInteropExports/excludeJsInteropExports regex]
[-XmethodNameDisplayMode (NONE|ONLY_METHOD_NAME|ABBREVIATED|FULL)]
[-X[no]closureFormattedOutput] [module]
Run with no module, the program prints the line Usage: at least one module must be supplied. The flags that matter every day:
| Flag | Purpose | Default |
|---|---|---|
|
The TCP port of the code server. |
|
|
A directory of GWT source prepended to the class path used for compiling. Repeatable. Under Maven the plugin passes one per source root. |
none |
|
The directory into which the files for launching Super Dev Mode, including the stub |
none (use the bookmarklets) |
|
The root of the tree where the code server writes compiler output ( |
a temporary directory |
|
The address for the code server and its web server. |
|
|
Reuses data from the previous compile. |
on |
|
Compiles the modules once when the server starts. |
on, switched off by the code server when incremental |
|
Script style: |
|
|
Fixes a deferred-binding property, for example |
none |
|
Stop if any input file has an error, even if unused. |
off |
|
The Java source level. The help text and the Developer Guide are right: the default is 1.8 (a default argument registered in |
1.8 |
|
Allows |
off |
|
Compile (and recompile) once and exit with status 0 on success. Useful in a continuous-integration check that the code server can build the module. |
off |
Triggering a recompile: bookmarklets or launcherDir
There are two ways to tell the browser "use the code server’s build of this module". Both end up in the same state: the
original *.nocache.js of the page finds a redirect and loads the code server’s output.
Bookmarklets
When you start the code server without -launcherDir, you compile and deploy the application once, serve its host page from
your own server, and then open the code server page (http://127.0.0.1:9876/). It lists two bookmarklets, Dev Mode On
and Dev Mode Off, to drag onto the bookmarks bar. On your application page click Dev Mode On, pick the module and press
Compile: the code server compiles the module, stores its URL in the page’s session storage and reloads the page. The page’s
own bookshelf.nocache.js finds the entry and redirects to the code server’s copy:
window.sessionStorage["__gwtDevModeHook:bookshelf"]
// returns "http://127.0.0.1:9876/bookshelf/bookshelf.nocache.js"
The key is stored in session storage, so it is per browser tab and disappears when the tab is closed. Dev Mode Off removes it and the page returns to the deployed output. The compile button in the dialog is itself a bookmarklet that can be dragged to the toolbar.
The launcherDir approach
With -launcherDir the code server writes a stub bookshelf.nocache.js into that directory. If you make the directory part
of your web application (the archetype’s env-dev profile adds it as an extra Jetty resource base, and
gwt:codeserver and gwt:devmode both write to it), the host page’s script tag loads the stub instead of the real
bootstrap. The stub inserts the code server’s recompile script at the top of the page head, and that script asks the code
server to recompile on every page reload. Its source is short; the relevant part of the file written on the scratch
application reads:
var hostName = $wnd.location.hostname;
var serverUrl = 'http://' + hostName + ':9876';
var module = 'bookshelf';
var nocacheUrl = serverUrl + '/recompile-requester/' + module;
and, if the script cannot be loaded, it shows a confirm dialog:
Couldn't load bookshelf from Super Dev Mode
server at http://localhost:9876.
Please make sure this server is ready.
Do you want to try again?
Source: GWT repository — stub.nocache.js
The two approaches compare as follows:
| Aspect | Bookmarklets | launcherDir stub |
|---|---|---|
Setup |
Drag two bookmarklets once per browser. |
One path in the build; nothing in the browser. |
Reload behaviour |
After Dev Mode On the page recompiles when you press Compile in the dialog or the bookmarklet. |
Every page reload asks the code server to recompile and waits for the result. |
Host page needs |
A deployed build of the application (its |
Nothing deployed: the stub is the module’s bootstrap in development. |
Works for |
Any server, including one you do not control. |
A server that can serve the launcher directory as static resources. |
Danger |
None specific. |
The stub must never reach production (see the security section). |
Incremental compiles
Draft-mode compiling alone would still take seconds per change. SDM adds incremental compilation
(-incremental, on by default): the code server keeps a rebuild cache of the compiled types and, on the next compile, only
re-traverses types that depend on a changed source file. The release notes add that it also caches this data on disk, which
speeds up the first compile after a restart.
Incremental compilation compiles one permutation per request. The bookmarklet or the stub sends the browser’s actual binding
properties (the user.agent and locale that deferred binding would choose), so the code server compiles exactly the
permutation your browser will run. The first request in the scratch application, issued by hand without those properties,
shows what happens when the properties expand to more than one permutation:
[INFO] GET /recompile/bookshelf
[INFO] Job com.example.bookshelf.App_1_0
[INFO] starting job: com.example.bookshelf.App_1_0
[INFO] binding: user.agent=safari
[INFO] Current binding properties are expanding to more than one permutation but incremental compilation requires that each compile operate on only one permutation.
[INFO] 0,022s total -- Compile completed
With both properties given (locale and user.agent) the first compile of the Bookshelf, which has three locales and two user
agents, succeeded and the next edit of one string was recompiled much faster:
[INFO] GET /recompile/bookshelf
[INFO] binding: locale=en
[INFO] binding: user.agent=safari
[INFO] Unification traversed 26992 fields and methods and 2568 types. 2527 are considered part of the current module ...
[INFO] Linking per-type JS with 2506 new/changed types.
[INFO] Source Maps Enabled
[INFO] Compilation succeeded -- 9,149s
[INFO] 9,375s total -- Compile completed
(after changing one @DefaultMessage string)
[INFO] binding: locale=en
[INFO] binding: user.agent=safari
[INFO] Unification traversed 1103 fields and methods and 844 types. 8 are considered part of the current module ...
[INFO] Linking per-type JS with 8 new/changed types.
[INFO] Compilation succeeded -- 0,485s
[INFO] 0,563s total -- Compile completed
The first compile took 9.1 s, the incremental one 0.56 s with 8 changed types instead of 2506. A request with no change at
all is answered without compiling (skipped compile because no input files have changed, 13 ms). A restart of the code
server is faster than the first start because of the on-disk cache (3.9 s for the same module in the last run). Times are from a
laptop and only meant as orders of magnitude.
To shorten the cold compile, narrow the permutations for development with -setProperty, or in a development module with
set-property (for example user.agent fixed to the browser you use). The module-XML side of that is covered on
Compiler & Compilation.
Debugging in the browser with source maps
Because SDM runs JavaScript, you debug it in the browser’s devtools. The compiler emits a source map (Source Maps
Enabled appears in the compile log; since 2.12.0 source maps are on in all browsers), and the compiled .cache.js ends with a
sourceMappingURL comment that points to the code server:
//# sourceMappingURL=http://127.0.0.1:9876/sourcemaps/bookshelf/DF97226FAEF9B2B2AA29587BF7177179_sourcemap.json
The devtools then request the Java files themselves from the code server, so the Sources panel shows com/example/bookshelf/client/...
files you can set breakpoints in. The article describes the URL shape; on the scratch application:
curl -s http://127.0.0.1:9876/sourcemaps/bookshelf/com/example/bookshelf/client/App.java
returned the file after the first compile (the status code is 200 with Content-Type: text/plain) and a 404 with the page message
This module hasn't been compiled yet. before it. This is also the first sign of the security caveat below: the source of the
module is served to whoever asks.
Plan your debugging session around what SDM is and is not:
-
Breakpoints and stepping in the Java files work. The article recommends Chrome, where support is best, and notes that you may have to enable source maps in the devtools settings.
-
Variables are JavaScript values: the field names and values you see in the scope panel are those of the compiled code, not Java ones.
-
No JVM checks. SDM does not run the application in a JVM, so some runtime checks do not happen; the article gives the array index out of bounds as an example. The production compile can also turn off or reduce checks that SDM’s draft build still performs, so run a production build before release.
-
Logging.
GWT.logwrites to the browser console in SDM (and is removed from production output).GWT.debugger()emits a JavaScriptdebuggerstatement that stops when the devtools are open, with no effect in server code. The Javadoc for the sharedGWTclass documents both;java.util.loggingcan be routed to the console as well (see Logging).
The following change to the Bookshelf presenter uses com.google.gwt.core.shared.GWT rather than the client class, so that the
presenter stays unit-testable in a plain JVM; the module compiled under the code server with the two calls, and the string
Loading books is present in the compiled output.
import com.google.gwt.core.shared.GWT;
public void load(int start, int length) {
GWT.log("Loading books " + start + ".." + (start + length));
service.getBooks(start, length, new AsyncCallback<BookPage>() {
@Override
public void onSuccess(BookPage page) {
display.showRows(start, page.getBooks(), page.getTotal());
}
@Override
public void onFailure(Throwable caught) {
GWT.log("getBooks failed", caught);
GWT.debugger(); // stops here when the browser devtools are open
display.showError(caught.getMessage());
}
});
}
Never log secrets, session tokens or whole user records with GWT.log or System.out even in development: console output
reaches screenshots, bug reports and browser extensions. Remove any GWT.debugger() before merging; it is harmless to users with
closed devtools but is a leftover that makes a production page stop for anyone who opens them.
Debugging from an IDE and the server side
No official page documents an IDE-specific procedure for SDM, so only the general shape is given here.
-
Client code. An IDE that can attach to the browser’s JavaScript debugger and honours source maps can set breakpoints in
.javafiles in the same way the devtools do, because the maps and the sources both come from the code server URL. This is a feature of the IDE, not of GWT, and works only while the code server is running. -
Shared and server code. Code in the
sharedmodule that is also compiled for the JVM, and everything in the server module, runs in an ordinary JVM, so a normal Java debugger attached to the servlet container (or tomvn jetty:run) works as always. Attach with the JVM’s standard-agentlib:jdwpoption inMAVEN_OPTS, or use your IDE’s Maven or Spring Boot run configuration with Debug. -
Presenters and plain Java. The best IDE debugging experience for client logic remains a JUnit test of a presenter whose view and service are fakes (Testing covers it); no code server or browser is needed.
-
The code server’s own JVM. To debug a generator or an annotation processor that runs inside the compiler, start the code server (or the Maven goal’s forked JVM,
jvmArgs) with a JDWP agent. This is rarely needed.
The tutorial in the official documentation debugs StockWatcher in an IDE with classic Dev Mode ("Debug As" in Eclipse). That procedure no longer applies to current GWT, and the Eclipse plugin text it relies on is historical.
Source: GWT — Tutorial: Debugging
DevMode today
com.google.gwt.dev.DevMode is still shipped and still the main class of the old ant devmode and Eclipse launch
configurations. In 2.13.1 it is a thin shell around SDM, and its role changed in 2.13.0:
-
-superDevModeis on by default (ArgHandlerSuperDevMode.getDefaultValue()returnstrue). Setting it to-nosuperDevModeis the deprecated classic mode. -
DevMode starts the code server by reflection (
SuperDevListener); ifgwt-codeserveris not on the class path the log says:Unable to find main() method for Super Dev Mode code server. Hint: verify that gwt-codeserver.jar is in your classpath. -
-[no]startServer(default on) starts an embedded servlet container for the directory given with-war.-noserveris a documented alias of-nostartServerinDevModeBase. With it you run your own server and DevMode only compiles and starts the code server. -
-startupUrl urladds a URL that DevMode offers to open ("Automatically launches the specified URL"); a URL without a host is taken aslocalhostand the embedded server’s port. -
-portis the embedded web server’s port (8888),-codeServerPortthe code server’s (9876 in SDM, 9997 for classic).-bindAddressdefaults to127.0.0.1. -
-war,-deploy,-extra,-workDir,-style,-setProperty,-incrementaland-sourceLevelwork as for the compiler and the code server.
DevMode opens a Swing window. Started with -Djava.awt.headless=true on the scratch application with -noserver, it fails
before doing anything else:
java.lang.RuntimeException: Error running on Swing UI thread
at com.google.gwt.dev.SwingUI.invokeAndWait(SwingUI.java:411)
...
Caused by: java.awt.HeadlessException
Source: GWT repository — DevMode.java
That makes DevMode unsuitable for servers, containers and CI. mvn gwt:codeserver, which has no GUI, is the replacement, and
the plugin keeps gwt:devmode only for standalone applications that have no server of their own (client code only, or CORS
to an API). For those, point startupUrls at a host page from the module’s public path.
The 2.13 static-file-only server
Up to 2.12, -startServer launched an embedded Jetty that also ran your servlets from WEB-INF (so you could serve RPC from
DevMode). The 2.13.0 release notes changed the default:
DevMode server defaults to only serving static files.
https://www.gwtproject.org/release-notes.html#Release_Notes_2_13_0
The default server class is now StaticResourceServer: a Jetty ResourceHandler that serves the -war directory and
nothing else (no servlets, no web.xml). The previous launcher is still present, selected with
-server com.google.gwt.dev.shell.jetty.JettyLauncher, but the release notes describe it as "due to be removed", and the 2.11
notes had already deprecated "using DevMode as an application server". The official advice is to split the client and server
class paths, or to implement a ServletContainerLauncher that runs another server (the notes link a sample project that
does this), or simply to run your servlet container separately.
# DevMode with the legacy launcher (not recommended, due to be removed)
java -cp "$CP" com.google.gwt.dev.DevMode \
-server com.google.gwt.dev.shell.jetty.JettyLauncher \
-war target/gwt/launcherDir \
-startupUrl index.html \
com.example.bookshelf.App
Source: GWT — Release Notes 2.13.0
The -server flag takes servletContainerLauncher[:args], either a fully qualified class or the name of a
ServletContainerLauncher registered with the Java ServiceLoader. Specifying -server overrides -noserver.
For a real servlet container or Spring Boot application, which is what the Bookshelf uses, none of this is needed: run the
server as you do in production (here the Maven Jetty plugin with -Denv=dev so the launcher directory is served) and run
gwt:codeserver beside it.
# terminal 1: the client side, recompiles on demand
mvn gwt:codeserver -pl bookshelf-client -am
# terminal 2: the server side (Jetty 12 EE 10 with the launcher directory as an extra resource base)
mvn -pl bookshelf-server -Denv=dev org.eclipse.jetty.ee10:jetty-ee10-maven-plugin:12.1.10:run -Djetty.http.port=8081
Open http://localhost:8081/ and the browser asks the code server (on 9876) for the module. A Spring Boot server works the same
way as long as it serves the launcher directory as a static resource location in its development profile; the GWT side does not
care which server delivers the host page. The same arrangement is the answer to the DG section on EJBs: GWT provides the
code server or the -noserver option for that case.
Classic Dev Mode and the plugins: history only
Before GWT 2.7 (and still in the 2.x documentation text), development mode meant the JVM executing the Java bytecode of your
client code, connected to a regular browser through a browser plugin (the GWT Developer Plugin), with the Java debugger
of the IDE attached to that JVM. It gave full Java debugging, and the DevMode window showed a log tree with GWT.log messages,
a Restart Server button for the embedded Jetty, and the -logLevel SPAM option for the engine’s internal messages. The
approach needed a plugin per browser. The 2.8.0 release notes list classic Dev Mode under deprecations (with a
temporary switch back, gwt.args='-devMode', for test cases), and since 2.7 launching DevMode starts Super Dev Mode. A modern application cannot use the plugin; its
remnants are the flags -nosuperDevMode and
-codeServerPort 9997 and the screenshots of the Swing window in the older text.
The first edition of the Manning book GWT in Action (Hanson and Tacy, 2007; it targets GWT 1.3 and 1.4) describes the earlier
hosted mode, a launcher class GWTShell with an embedded browser and Tomcat, for debugging in an IDE; that is the ancestor of the
mechanism above and none of its procedures, class names or screenshots apply to GWT 2.13. Everything it says about breakpoints in
client Java belongs to the pre-Super-Dev-Mode era.
Source: GWT — Release Notes 2.8.0
Security: the code server must never be exposed
The Super Dev Mode article is explicit that the code server has no authentication and hands all of your Java source code to
anyone who asks, and therefore recommends running it only on localhost or behind a firewall. In the code (WebServer.java) every static response carries Access-Control-Allow-Origin: *, which was verified
on the scratch application:
curl -s -D - -o /dev/null http://127.0.0.1:9876/bookshelf/bookshelf.nocache.js | grep -i access-control
# Access-Control-Allow-Origin: *
Source: GWT repository — WebServer.java
Treat the port as a development-machine-only interface:
-
Keep the default
-bindAddress 127.0.0.1. Do not bind to0.0.0.0or forward the port from a shared host, VM or container to a network you do not control: anyone who can reach it can read your sources through/sourcemaps/...and trigger compiles (including/clean, which wipes the disk cache). For testing from a phone, use a trusted network and shut the code server down afterwards. -
The article says that
httpsis not supported (a referenced upstream issue is gwtproject/gwt#7535), so a host page served overhttpsloads a script from anhttporigin, which browsers treat as mixed content and may block. Test withhttphosts or use a browser setting for local development. -
Never deploy the launcher directory or its stub
*.nocache.js. The stub names a code server on the page’s host and port 9876 and runs whatever script that URL returns. The production artifact is the output ofmvn package(gwt:compile), nottarget/gwt/launcherDir. Keep the Mavenenv-devprofile, and any Spring Boot development profile that exposes the directory, out of production configurations. -
Source maps and the sources they reference are also sensitive when produced by a production compile. Whether to publish them is a deployment decision discussed on Linkers & Bootstrap and XSRF, RPC & Server Security.
-
The code server and the Swing DevMode are development tools: they hold no user data, but they run your build, so run them as an unprivileged user and do not point them at untrusted modules.
Worked example: Bookshelf development session
This session combines the pieces on the Bookshelf scratch application: the server, the code server, an edit, an error and the recovery.
-
Start the two processes as in the previous section, then open
http://localhost:8081/in Chrome. The stub asks the code server to compile; the first compile of the application takes about 9 s (3.9 s on a warm disk cache). -
Open the devtools, choose Sources and press the search shortcut to open
CatalogPresenter.java. Set a breakpoint on theservice.getBooks(...)line and reload: the compile is skipped (nothing changed) and the breakpoint is hit. -
Change a string in
AppMessages.javaand reload. The log showsCompiling 1 permutation, 8 new or changed types and a half-second compile. -
Introduce a typo (an
intafter the@DefaultMessageannotation). The reload still shows the previous version, and the code server log shows the errors (below). -
Remove the typo and reload: the next compile succeeds and the page updates.
The failing recompile of step 4 answered the request with {"moduleNames":["bookshelf"],"status":"failed"} and logged:
[INFO] Tracing compile failure path for type 'com.example.bookshelf.client.i18n.AppMessages'
[INFO] [ERROR] Errors in 'file:.../bookshelf-client/src/main/java/com/example/bookshelf/client/i18n/AppMessages.java'
[INFO] [ERROR] Line 6: The annotation @Messages.DefaultMessage is disallowed for this location
[INFO] [ERROR] Line 7: Syntax error, insert ";" to complete FieldDeclaration
[INFO] [ERROR] Line 7: Return type for the method is missing
[INFO] [ERROR] Aborting compile due to errors in some input files
[INFO] [ERROR] Compiler returned false
[INFO] [WARN] recompile failed
[INFO] [WARN] continuing to serve previous version
The last two lines explain the most common confusion of a new SDM user: after a compile error the browser keeps running the
last good build, so "my change does nothing" almost always means "read the code server’s terminal". The browser’s own
Network tab shows the failing /recompile/... response.
Troubleshooting and pitfalls
| Symptom | Cause | Fix |
|---|---|---|
A confirm dialog: |
The code server is not running yet, or listens on another host or port, or is bound to a different address than the page uses. |
Wait for |
My edit has no effect after a reload |
The recompile failed and the code server continues to serve the previous version ( |
Read the code server terminal for |
|
A manual call (curl or a script) without the |
Let the stub or bookmarklet send the properties, or pass them yourself ( |
|
Devtools asked for a source before the first successful compile of this module. |
Reload the application page so that the first compile runs. |
Old behaviour persists after changing module XML, a |
The incremental cache and the on-disk cache hold compiled data from before the change. |
Open |
|
|
Put |
|
|
Use |
|
|
Add |
After switching to |
The |
Recompile (the code server regenerates them) and serve the module output that the code server produces; do not copy a stale directory. |
The page does not use the code server at all |
The page’s |
Use the launcherDir stub, or press Dev Mode On again on the tab. |
Breakpoints in Java files never hit, or lines are off |
The browser did not apply source maps (disabled in the devtools settings), or the page runs a cached old build. |
Enable source maps in the devtools, hard-reload with the cache disabled, and check that the |
A bug appears only in the production build |
SDM compiles in draft mode and omits checks the JVM would perform. The Developer Guide states the principle that if it runs in development mode and compiles, it should behave the same, with rare exceptions. |
Run |
|
Wildcard project selection is a Maven 4 feature; Maven 3.9 does not support it. |
Use |
Source: GWT — FAQ: Troubleshooting
Where older material is outdated
-
Articles and tutorials that start "development mode" with
ant devmode,webAppCreatoror an Eclipse launch configuration describe the classic flow.webAppCreatoris deprecated and its generator classes were removed in 2.12.0, so a new project starts from a Maven archetype (see Getting Started and Build Tools: Maven & Gradle). -
The Developer Guide page "Compiling and Debugging" still documents the DevMode options with the older defaults (the embedded Jetty serving your servlets, a GUI with a Restart Server button) and does not mention the 2.13 change; the release notes do.
-
The
-sourceLevelhelp text and the guide say the default is 1.8, which is correct for the command-line tools; the Java 12-17 features of 2.12.0 and later need an explicit-sourceLevel 17(theautovalue resolves to the running JVM’s level). -
The book’s hosted mode and the plugin-based flow of 2.0 to 2.6 are historical, as above.