GWT: Google Web Toolkit for Rich Interfaces
Google Web Toolkit (GWT) is a development framework that lets you build and optimize complex browser-based applications using Java. Instead of writing JavaScript directly, you write your client-side logic in Java, and the GWT compiler translates it into highly optimized JavaScript that runs across all major browsers.
While newer frameworks like React and Angular dominate today's conversations, GWT remains relevant for large enterprise applications, particularly where teams have deep Java expertise and want to share code between client and server.
Why Choose GWT?
The core value proposition of GWT is writing frontend code in Java. This brings several advantages:
- Type safety across your entire codebase
- Code sharing between client and server (validation logic, DTOs, utilities)
- Powerful tooling from the mature Java ecosystem (refactoring, static analysis, debugging)
- Automatic optimization including dead-code elimination and minification
Setting Up a GWT Project
The easiest way to start is with Maven. Add the GWT dependencies and plugin to your pom.xml:
<dependency>
<groupId>com.google.gwt</groupId>
<artifactId>gwt-user</artifactId>
<version>2.10.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.gwt</groupId>
<artifactId>gwt-dev</artifactId>
<version>2.10.0</version>
<scope>provided</scope>
</dependency>
Every GWT module needs a .gwt.xml descriptor file that defines entry points and inherited modules:
<module rename-to="myapp">
<inherits name="com.google.gwt.user.User"/>
<inherits name="com.google.gwt.user.theme.clean.Clean"/>
<entry-point class="com.example.client.MyApp"/>
<source path="client"/>
<source path="shared"/>
</module>
Building Your First Interface
The entry point class implements EntryPoint and its onModuleLoad() method is called when the application starts:
package com.example.client;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.*;
public class MyApp implements EntryPoint {
public void onModuleLoad() {
Button clickButton = new Button("Click Me");
Label messageLabel = new Label();
clickButton.addClickHandler(event ->
messageLabel.setText("Hello from GWT!")
);
VerticalPanel panel = new VerticalPanel();
panel.add(clickButton);
panel.add(messageLabel);
RootPanel.get("appContainer").add(panel);
}
}
The RootPanel.get("appContainer") call attaches your widgets to a <div id="appContainer"> element in the host HTML page.
Widgets and Panels
GWT provides a rich widget library. Widgets are UI components (buttons, text boxes, labels), while Panels are containers that manage layout:
| Widget/Panel | Purpose |
|---|---|
Button |
Clickable button |
TextBox |
Single-line text input |
Label |
Non-interactive text |
VerticalPanel |
Stacks children vertically |
HorizontalPanel |
Arranges children in a row |
FlowPanel |
Renders as a simple <div>
|
DockLayoutPanel |
North/South/East/West/Center layout |
Communicating with the Server: GWT-RPC
One of GWT's standout features is GWT-RPC, which allows type-safe remote procedure calls. You define a service interface, its async counterpart, and a server implementation.
Define the synchronous service interface:
@RemoteServiceRelativePath("greet")
public interface GreetingService extends RemoteService {
String greetUser(String name);
}
Define the async interface used by the client:
public interface GreetingServiceAsync {
void greetUser(String name, AsyncCallback<String> callback);
}
Implement the service on the server:
public class GreetingServiceImpl extends RemoteServiceServlet
implements GreetingService {
@Override
public String greetUser(String name) {
return "Hello, " + name + "!";
}
}
Call it from the client asynchronously:
GreetingServiceAsync service = GWT.create(GreetingService.class);
service.greetUser("Alice", new AsyncCallback<String>() {
@Override
public void onSuccess(String result) {
Window.alert(result);
}
@Override
public void onFailure(Throwable caught) {
Window.alert("Error: " + caught.getMessage());
}
});
Development Mode and Compilation
During development, GWT's Super Dev Mode lets you debug directly in the browser using source maps, so you can step through your original Java code. Launch it with:
mvn gwt:codeserver
For production, compile your application to optimized JavaScript:
mvn gwt:compile
The compiler produces separate, permutation-specific JavaScript for different browsers and locales, ensuring each user downloads only the code they need.
Best Practices
- Use UiBinder for declarative UI layouts, keeping markup separate from logic
-
Leverage code splitting with
GWT.runAsync()to load large modules on demand -
Share DTOs and validation in a
sharedpackage accessible to both client and server - Enable draft compilation during development for faster build times
Top comments (0)