Google Web Toolkit (GWT) is an open source web development framework that allows developers to easily create high-performance AJAX applications using Java. With GWT, you are able to write your front end in Java, and it compiles your source code into highly optimized, browser-compliant JavaScript and HTML. "Writing web apps today is a tedious and error-prone process. You spend 90% of your time working around browser quirks, and JavaScript's lack of modularity makes sharing, testing, and reusing AJAX components difficult and fragile. It doesn't have to be that way," reads the Google Web Toolkit site.
In this tutorial, you learn how the above principles are applied to real applications. At the same time, you are introduced to NetBeans IDE's support for GWT and you build a simple application that makes use of some of these features.
Contents

To follow this tutorial, you need the following software and resources.
Notes:

Begin by using the IDE to generate a basic source structure. Once you have it, you can study it in some detail in order to understand the inner workings of GWT.
The source structure of the application you create must include the GWT JAR files, the GWT module project configuration file, as well as some standard artifacts such as the Java entry point. Since you are using an IDE, you should not need to manually create all these files. Instead, let a wizard do the work for you. Specifically, the final panel of the New Web Application wizard is very useful in the context of creating a GWT application.

The IDE creates the HelloGWT project. The project contains all of your sources, libraries, and project metadata, such as the project's Ant build script. The project opens in the IDE. You can view its logical structure in the Projects window (Ctrl-1):

Right-click the project and choose Run. The application is built and a web archive (WAR) is created. It is deployed to the server. The server starts, if it is not running already. Your computer's default browser opens and the welcome page of the application is displayed:

Click the button and the text below it disappears:

In the next section, you explore each of the generated files in detail and examine how the simple application above was created.
The IDE's New Web Application wizard created several source files. Take a look at the files and see how they relate to each other within the context of a GWT application.
<?xml version="1.0" encoding="UTF-8"?>
<module>
<inherits name="com.google.gwt.user.User"/>
<entry-point class="org.yournamehere.client.MainEntryPoint"/>
<!-- Do not define servlets here, use web.xml -->
</module>
The elements in the default project module are as follows:
package org.yournamehere.client;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.Widget;
public class MainEntryPoint implements EntryPoint {
/** Creates a new instance of MainEntryPoint */
public MainEntryPoint() {
}
/**
The entry point method, called automatically by loading a module
that declares an implementing class as an entry-point
*/
public void onModuleLoad() {
final Label label = new Label("Hello, GWT!!!");
final Button button = new Button("Click me!");
button.addClickListener(new ClickListener(){
public void onClick(Widget w) {
label.setVisible(!label.isVisible());
}
});
RootPanel.get().add(button);
RootPanel.get().add(label);
}
}
The onModuleLoad() method in the default entry point class adds the following to the application:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta name='gwt:module' content='org.yournamehere.Main=org.yournamehere.Main'>
<title>Main</title>
</head>
<body>
<script language="javascript" src="org.yournamehere.Main/org.yournamehere.Main.nocache.js"></script>
</body>
</html>
The elements in the default host page are as follows:
In this section, you display a random quote on the web page. This example application familiarizes you with the various components of a GWT application. The random quote is to be selected from a list of quotes stored on the server. Every second the application retrieves the random quote provided by the server and displays it on the web page in true AJAX style, that is, without the user needing to refresh the page.
In the process of creating this functionality, you make use of a GWT service. In this context, a service has nothing to do with web services. A service is the code that the client invokes on the server side to access the server's functionality and display it on the client side.
The NetBeans GWT plugin provides a wizard that generates the basic service classes for you. In this subsection, you are introduced to this wizard.

Click Finish. The files listed in the New File wizard (shown in the above screenshot) are generated, and the Projects window automatically updates to reflect changes:
Note: A small tweak is required. In the generated implementation class, called GWTServiceImpl, you need to import org.yournamehere.client.sampleservice.GWTService, instead of org.yournamehere.client.GWTService.
The GWT RPC Service wizard created several source files. Here, look at the files and see how they relate to each other within the context of a GWT service.
package org.yournamehere.client.sampleservice;
import com.google.gwt.user.client.rpc.RemoteService;
public interface GWTService extends RemoteService {
public String myMethod(String s);
}
GWTServiceAsync: The client-side definition of the asynchronous version of the service. It provides a callback object that enables the asynchronous communication between server and client.
package org.yournamehere.client.sampleservice;
import com.google.gwt.user.client.rpc.AsyncCallback;
public interface GWTServiceAsync {
public void myMethod(String s, AsyncCallback callback);
}
GWTServiceImpl: The servlet that implements the interface and provides the functionality for retrieving a random quote via RPC.
package org.yournamehere.server.sampleservice;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import org.yournamehere.client.sampleservice.GWTService;
public class GWTServiceImpl extends RemoteServiceServlet implements GWTService {
public String myMethod(String s) {
// Do something interesting with 's' here on the server.
return "Server says: " + s;
}
}
GWTServiceUsageExample: The sample user interface generated as a test client. It instantiates the service.
package org.yournamehere.client.sampleservice;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.rpc.ServiceDefTarget;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
public class GWTServiceUsageExample extends VerticalPanel {
private Label lblServerReply = new Label();
private TextBox txtUserInput = new TextBox();
private Button btnSend = new Button("Send to server");
public GWTServiceUsageExample() {
add(new Label("Input your text: "));
add(txtUserInput);
add(btnSend);
add(lblServerReply);
// Create an asynchronous callback to handle the result.
final AsyncCallback callback = new AsyncCallback() {
public void onSuccess(Object result) {
lblServerReply.setText((String)result);
}
public void onFailure(Throwable caught) {
lblServerReply.setText("Communication failed");
}
};
// Listen for the button clicks
btnSend.addClickListener(new ClickListener(){
public void onClick(Widget w) {
// Make remote call. Control flow will continue immediately and later
// 'callback' will be invoked when the RPC completes.
getService().myMethod(txtUserInput.getText(), callback);
}
});
}
public static GWTServiceAsync getService(){
// Create the client proxy. Note that although you are creating the
// service interface proper, you cast the result to the asynchronous
// version of
// the interface. The cast is always safe because the generated proxy
// implements the asynchronous interface automatically.
GWTServiceAsync service = (GWTServiceAsync) GWT.create(GWTService.class);
// Specify the URL at which our service implementation is running.
// Note that the target URL must reside on the same domain and port from
// which the host page was served.
//
ServiceDefTarget endpoint = (ServiceDefTarget) service;
String moduleRelativeURL = GWT.getModuleBaseURL() + "gwtservice";
endpoint.setServiceEntryPoint(moduleRelativeURL);
return service;
}
}
Note: Before continuing, you need to tweak the moduleRelativeURL string in the snippet above to the following, so that it includes the subpackage you just created:
String moduleRelativeURL = GWT.getModuleBaseURL() + "sampleservice/gwtservice";Change the entry point class's onModuleLoad() method to the following:
public void onModuleLoad() {
RootPanel.get().add(new GWTServiceUsageExample());
}
Note: After modifying the onModuleLoad() method, you need to add an import statement to the sampleservice.GWTServiceUsageExample class. To do so, click on the lightbulb that displays in the left column where the GWTServiceUsageExample() is listed in the Source Editor and choose Add Import for org.yournamehere.client.sampleservice.GWTServiceUsageExample:
In the Projects window, right-click the project node and choose Run. The server starts, if it is not running already. The project is recompiled and deployed to the server. The browser opens to display a text field. Type in a message and click the button. A label appears with the message you sent:
You have successfully tested the generated service. In the next section, you can do something useful with it, now that you know it works.
In this section, you tweak and extend the classes that were examined in the previous subsection. At the end of this subsection, you will have completed the AJAX random quote generator.
public interface GWTService extends RemoteService {
public String myMethod();
}
Do the same in the asynchronous service, so that this interface is like this:
public interface GWTServiceAsync {
public void myMethod(AsyncCallback callback);
}
In GWTServiceImpl, implement the interface as follows:
public class GWTServiceImpl extends RemoteServiceServlet implements GWTService {
private Random randomizer = new Random();
private static final long serialVersionUID = -15020842597334403L;
private static List quotes = new ArrayList();
static {
quotes.add("No great thing is created suddenly - Epictetus");
quotes.add("Well done is better than well said - Ben Franklin");
quotes.add("No wind favors he who has no destined port - Montaigne");
quotes.add("Sometimes even to live is an act of courage - Seneca");
quotes.add("Know thyself - Socrates");
}
public String myMethod() {
return (String) quotes.get(randomizer.nextInt(4));
}
}
Note: Right-click anywhere in the Source Editor and choose Fix Imports, to let the IDE create the correct import statements. When you do so, make sure to select java.util.Random, instead of com.google.gwt.user.client.Random:
Cut and paste the relevant code snippets from the generated usage example class (GWTServiceUsageExample) to the entry point class (MainEntryPoint). First, copy the getService() method to the entry point class:
public static GWTServiceAsync getService() {
// Create the client proxy. Note that although you are creating the
// service interface proper, you cast the result to the asynchronous
// version of
// the interface. The cast is always safe because the generated proxy
// implements the asynchronous interface automatically.
GWTServiceAsync service = (GWTServiceAsync) GWT.create(GWTService.class);
// Specify the URL at which our service implementation is running.
// Note that the target URL must reside on the same domain and port from
// which the host page was served.
//
ServiceDefTarget endpoint = (ServiceDefTarget) service;
String moduleRelativeURL = GWT.getModuleBaseURL() + "sampleservice/gwtservice";
endpoint.setServiceEntryPoint(moduleRelativeURL);
return service;
}
Change the onModuleLoad() method in the entry point class to the following:
/**
* The entry point method, called automatically by loading a module
* that declares an implementing class as an entry-point
*/
public void onModuleLoad() {
final Label quoteText = new Label();
Timer timer = new Timer() {
public void run() {
//create an async callback to handle the result:
AsyncCallback callback = new AsyncCallback() {
public void onFailure(Throwable arg0) {
//display error text if we can't get the quote:
quoteText.setText("Failed to get a quote");
}
public void onSuccess(Object result) {
//display the retrieved quote in the label:
quoteText.setText((String) result);
}
};
getService().myMethod(callback);
}
};
timer.scheduleRepeating(1000);
RootPanel.get().add(quoteText);
}
Note: Right-click in the Source Editor and choose Fix Imports in order to let the IDE create the correct import statements. When you do so, make sure to select com.google.gwt.user.client.Timer, instead of java.util.Timer. Delete GWTServiceUsageExample. To do so, right-click the class node in the Projects window and choose Delete. In the Projects window, right-click the project node and choose Run. When the application is deployed and the browser opens, you see a new quote received from the server, every other second:
In the next section, you apply a stylesheet to change the look and feel of the quotes.
In this section, you attach a stylesheet to the HTML host page. You also refer to it in the entry point class. Specifically, you need to set the style name of the label in the entry point class to the name of the style in the stylesheet. At runtime, GWT connects the style to the label and displays a customized label in the browser.
.quoteLabel {
color: white;
display: block;
width: 450px;
padding: 2px 4px;
text-decoration: none;
text-align: center;
font-family: Arial, Helvetica, sans-serif;
font-weight: bold;
border: 1px solid;
border-color: black;
background-color: #704968;
text-decoration: none;
}
The stylesheet editor should now show the following:
Attach the stylesheet to the HTML page (welcomeGWT.html). At the same time, add some text to introduce the application to the user. The new parts of the HTML page are highlighted below in bold:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta name='gwt:module' content='org.yournamehere.Main=org.yournamehere.Main'>
<title>Main</title>
<link rel="stylesheet" type="text/css" href="welcomeGWT.css">
</head>
<body>
<script language="javascript" src="org.yournamehere.Main/org.yournamehere.Main.nocache.js"></script>
<p>This is an AJAX application that retrieves a random quote from
the Random Quote service every second. The data is retrieved
and the quote updated without refreshing the page!</p>
</body>
</html>
In the entry point class, specify that, upon success, the style defined in the stylesheet should be applied to the label. The new line is highlighted in bold below:
public void onSuccess(Object result) {
//display the retrieved quote in the label:
quoteText.setText((String) result);
quoteText.setStyleName("quoteLabel");
}
As you code, notice that code completion can help you, suggesting ways of completing the code and showing you the related Javadoc:

In this tutorial, you have learnt the following:
Finally, open the Files window (Ctrl-2) and expand the build folder. (If the build folder is not present, you need to build the project again in order to have the IDE regenerate the build folder.) You should see something like this:

This folder is generated automatically by GWT when the application is compiled. The folder consists of a ready-to-deploy version of the client application. It contains, among other files, the following:
In conclusion, because the GWT framework handles browser-related code generation, as well as the creation of the lower-level XmlHttpRequest API code, you can take advantage of the framework to focus on the functionality that you want your applications to provide. Hence, as stated in the introduction, GWT lets you avoid the headaches associated with browser compatibility while simultaneously letting you offer users the same dynamic, standards-compliant experience that the Web 2.0 world typically provides. As this tutorial demonstrated, you can apply the GWT framework to write your complete front end in Java, because you know that you can let the GWT compiler convert Java classes to browser-compliant JavaScript and HTML. And, as also demonstrated, the IDE provides a complete set of tools for making all this easy and efficient, without the need to hand-code a GWT application's basic infrastructure.
This concludes the Introduction to the Google Web Toolkit Framework tutorial. For related and more advanced material, see the following resources:
You are viewing a mobilized version of this site...
View original page here