Introduction to the Google Web Toolkit Framework

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

Content on this page applies to NetBeans IDE 6.x-7.0

To complete this tutorial, you need the following software and resources.

Software or Resource Version Required
NetBeans IDE, Java bundle version 6.x
Java Development Kit (JDK) version 5 or more recent
GlassFish server
or
Tomcat servlet container
v3 or Open Source Edition 3.0.1
 
version 6.x
Google Web Toolkit (GWT) version 1.5 or more recent
NetBeans GWT plugin version 2.x

Notes:


Setting Up the Environment

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.

Creating the Source Structure of a GWT Application

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.

  1. Choose File > New Project (Ctrl-Shift-N; ⌘-Shift-N on Mac). Under Categories, select Web (or Java Web). Under Projects, select Web Application. Click Next.
  2. In step 2, Name and Location, type HelloGWT in Project Name. You can also specify the location of the project by typing in a path on your computer in Project Location field. Click Next.
  3. In the Server and Settings step, select any server that you have registered in the IDE. If you included Tomcat or the GlassFish server when installing the IDE, they display in the drop-down list.

    To register a server in the IDE, click the Add button to open a wizard that guides you through the registration process.
  4. Specify the Java version you are using. Click Next.

    Note: This tutorial supports GWT version 1.5 and higher. GWT 1.4 does not support Java EE 5, so if you are using this version you must also set the Java EE Version to 1.4. Otherwise, for example, Java EE 5 annotations will cause compilation errors.

  5. In the Frameworks step, select GWT.
    GWT listed in Frameworks panel of New Project wizard
    When you select the GWT framework, the following fields become available:
    • GWT Installation Folder: Specify the path to the folder where you downloaded the Google Web Toolkit at the start of this tutorial. If an incorrect path is specified, a red error message displays and you are not able to complete the wizard.
    • GWT Module: Specifies the name and location of the project module that the IDE will generate when you complete the wizard. The project module is an XML file that configures a GWT application. For example, it is used to specify the class instantiated by GWT when the module is loaded. Note that this field in the wizard also determines the main package of the application. By default, the main package is org.yournamehere and the project module is Main. For purposes of this tutorial, leave the default entries unchanged.
  6. Click Finish. 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 file structure in the Files window (Ctrl-2; ⌘-2 on Mac) and its logical structure in the Projects window (Ctrl-1; ⌘-1 on Mac).
    Projects window displaying HelloGWT project
  7. In the Projects window, right-click the project node 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.
    Hello GWT message displayed in browser
    Click the button and the text below it disappears.
    Text below button disappears

In the next section, you explore each of the generated files in detail and examine how the simple application above was created.

Examining the Source Structure of a GWT Application

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.

  • Main.gwt.xml: The project module XML file, contained in the project's root package, is an XML file that holds the complete application configuration needed by a GWT project. The default project module generated by the wizard looks as follows:
    <?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:

    • inherits: Specifies modules inherited by this module. In this simple case, we only inherit the functionality provided by the User module, which is built into the GWT framework. When your application becomes more complex, module inheritance lets you reuse pieces of functionality in a quick and efficient way.
    • entry-point: Refers to the class that will be instantiated by the GWT framework when the module is loaded.
    Note: For more information, see: Organizing Projects: Module XML Files.
  • MainEntryPoint.java: The class designating the application's main entry point, as specified in Main.gwt.xml. It extends the EntryPoint class, and when the GWT module is loaded by the framework, this class is instantiated and its onModuleLoad() method is automatically called. The default entry point generated by the wizard looks 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);
        }
    
    }
    In the above snippet, EntryPoint's default onModuleLoad() method adds the following components to the application:
    • Label: A new GWT Label is created, displaying the text, 'Hello, GWT!!!'. The label is added to the RootPanel by means of the final line of code, RootPanel.get().add(label).
    • Button: A new GWT Button is created, displaying the text, 'Click me!' together with a button listener, implemented by ClickListener. The button listener specifies that when a button is clicked, the label is hidden.
      public void onClick(Widget w) {
          label.setVisible(!label.isVisible());
      }
      The button is added to the RootPanel by means of the penultimate line of code.
      RootPanel.get().add(button)
  • welcomeGWT.html: The generated HTML host page, which is the designated welcome file for the application. The web.xml file uses the welcome-file element to specify that the host page is the initial page displayed in the browser when the application is deployed. The host page references the path to the JavaScript source code, and can reference the application stylesheet. The default host page generated by the wizard looks as follows:
    <!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 meta and script tags in the above snippet hold special significance for GWT:
    • meta: Points to the application's project directory. This tag provides the link between the HTML page and the application.
    • script: Imports code from the GWT framework's JavaScript file. This file contains the code required to bootstrap the GWT framework. It uses the configuration in the project module and then dynamically loads the JavaScript created by compiling the entry point to present the application. The JavaScript file is generated by the GWT framework when you run the application in hosted mode or when you compile the application.

Creating an AJAX Random Quote Generator

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 RPC (Remote Procedure Call) service.

Generating the Service Stubs

The NetBeans GWT plugin provides a wizard for creating an RPC service. The wizard generates the basic service classes for you. This subsection introduces the GWT RPC Service wizard.

  1. Click the New File ( New File icon ) icon in the IDE's main toolbar. In the New File wizard, the Google Web Toolkit category shows a file template named GWT RPC Service.
    First panel of the GWT RPC Service wizard
    Select GWT RPC Service and click Next.
  2. Optionally, fill in a subpackage where the files that will be generated will be stored. For purposes of this tutorial, type sampleservice as the Subpackage field.
    Second panel of GWT RPC Service wizard
    Note: By leaving the Create Usage Example Class option selected in this step, you allow the IDE to generate the GWTServiceUsageExample class, which can be used to invoke the service.
  3. Click Finish. The files listed in the New GWT RPC Service wizard (shown in the above image) are generated, and the Projects window automatically updates to reflect changes.
    Projects window updates containing newly-created files

Examining the Generated Classes

The GWT RPC Service wizard creates several source files. Here, look at the files and see how they relate to each other within the context of a GWT service.

For an extended description of GWT service classes, see Creating Services.

  • GWTService: The client-side definition of the service. This interface extends the RemoteService tag interface.
    package org.yournamehere.client.sampleservice;
    
    import com.google.gwt.user.client.rpc.RemoteService;
    import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;
    
    @RemoteServiceRelativePath("sampleservice/gwtservice")
    public interface GWTService extends RemoteService {
        public String myMethod(String s);
    }
  • GWTServiceImpl: The servlet that implements the GWTService 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;
        }
    
    }
  • GWTServiceAsync: An asynchronous interface, which is based on the original GWTService interface. 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<String> callback);
    }
  • GWTServiceUsageExample: The sample user interface generated as a test client. It can be used to invoke 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.Label;
    import com.google.gwt.user.client.ui.Widget;
    import com.google.gwt.user.client.ui.Button;
    import com.google.gwt.user.client.ui.TextBox;
    import com.google.gwt.user.client.ui.VerticalPanel;
    
    import com.google.gwt.event.dom.client.ClickEvent;
    import com.google.gwt.event.dom.client.ClickHandler;
    
    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<String> callback = new AsyncCallback<String>() {
                public void onSuccess(String result) {
                    lblServerReply.setText(result);
                }
    
                public void onFailure(Throwable caught) {
                    lblServerReply.setText("Communication failed");
                }
            };
    
            // Listen for the button clicks
            btnSend.addClickHandler(new ClickHandler(){
                public void onClick(ClickEvent event) {
                    // 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.
    
            return GWT.create(GWTService.class);
        }
    }

Now, modify the entry point class to invoke the service by instantiating a GWTServiceUsageExample object. Recall from the previous subsection that the GWTServiceUsageExample class was generated because you selected the Create Usage Example Class option in the GWT RPC wizard.

  1. In the onModuleLoad() method of the application's main entry point (MainEntryPoint.java), remove the GWT Label and Button, and add a new instance of GWTServiceUsageExample to the RootPanel.
    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 hint that displays in the left column where the GWTServiceUsageExample() method appears in the editor and choose Add Import for org.yournamehere.client.sampleservice.GWTServiceUsageExample.
    Fix Import support displayed in the editor
  2. In the Projects window, right-click the project node and choose Run. The server starts, if it is not running already. The project is compiled (recompiled in this case) 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.
    Browser output displaying user message

You successfully created a GWT RPC service using the IDE's GWT RPC wizard. You then added a GWTServiceUsageExample instance to the onModuleLoad() method of the application's main entry point, which causes the application to invoke the service when it is run. In the next section, you customize the service by extending the generated classes, and attach a stylesheet to the HTML host page.

Extending the Generated Classes

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 created a functioning version of the AJAX random quote generator.

  1. Recall that GWTServiceImpl is the servlet that implements the service you are creating.

    If you open your application's web.xml deployment descriptor, you see that a servlet declaration and mapping have already been added.

    <servlet>
        <servlet-name>GWTService</servlet-name>
        <servlet-class>org.yournamehere.server.sampleservice.GWTServiceImpl</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>GWTService</servlet-name>
        <url-pattern>/org.yournamehere.Main/sampleservice/gwtservice</url-pattern>
    </servlet-mapping>
    In the GWTServiceImpl class, you implement the GWTService interface with the logic that is specific to your service. To create a random quote generator, add the following code to GWTServiceImpl:
    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(5));
        }
    
    }
    Note: Right-click anywhere in the IDE's 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:
    Fix All Imports dialog
  2. Instead of having the generated usage example class (GWTServiceUsageExample) invoke the service, have it invoked directly from the application's entry point class (MainEntryPoint). Begin by copying GWTServiceUsageExample's getService() method and paste it into MainEntryPoint. (Changes in bold.)
    public class MainEntryPoint implements EntryPoint {
    
        /**
         * Creates a new instance of MainEntryPoint
         */
        public MainEntryPoint() {
        }
    
        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.
    
            return GWT.create(GWTService.class);
        }
    
        ...
  3. Right-click in the editor and choose Fix Imports. The following three import statements are added to MainEntryPoint.
    import com.google.gwt.core.client.GWT;
    import org.yournamehere.client.sampleservice.GWTService;
    import org.yournamehere.client.sampleservice.GWTServiceAsync;
  4. 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);
    
    }
  5. Right-click in the editor and choose Fix Imports. When you do so, make sure to select com.google.gwt.user.client.Timer, and com.google.gwt.user.client.ui.Label.
    Fix All Imports dialog
  6. Delete the class GWTServiceUsageExample. It will no longer compile. Because the application is able to call the service from its main entry point class, you no longer need the GWTServiceUsageExample usage example class to invoke the service.
  7. Although the generated stubs for GWTService and GWTServiceAsync provided you with a String parameter for myMethod(), you do not need it for the random quote generator.

    In the GWTService class, remove the String parameter from myMethod() so that the interface is as follows.
    public interface GWTService extends RemoteService {
        public String myMethod();
    }
  8. The method signature for the asynchronous service (GWTServiceAsync) must match that of GWTService (but include an AsyncCallback object as the final parameter). Therefore, remove the String parameter from myMethod() so that the interface is as follows.
    public interface GWTServiceAsync {
        public void myMethod(AsyncCallback callback);
    }
    See Making Asynchronous Calls and Getting Used to Asynchronous Calls in the official GWT documentation for more information on the asynchronous service interface.
  9. Run the project. When the application is deployed and the browser opens, you see a new quote received from the server after every second:
    AJAX quote generator displayed in browser

In the next section, you apply a stylesheet to change the appearance of the quotes.

Customizing the Appearance

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.

  1. Create a stylesheet called welcomeGWT.css. To create the file, right-click the Web Pages node in the Projects window and choose New > Other. The New File wizard displays.
  2. Under Categories choose Web, then choose Cascading Style Sheet under File Types. When you complete the wizard, the new empty file opens in the editor.
  3. Create the following quoteLabel selector for the new stylesheet.
    .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.
    CSS preview displayed in the editor

    To display the CSS Preview and Style Builder, choose Window > Other from the main menu.

  4. Link to the stylesheet from the application welcome 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'>
            <link rel="stylesheet" type="text/css" href="welcomeGWT.css">
    
            <title>Main</title>
        </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>
  5. Within the onModuleLoad() method of the entry point class (MainEntryPoint.java), 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 type, press Ctrl-Space to enable the IDE's built-in code completion. The code completion works by triggering a pop-up window that suggests ways of completing the code, and showing you the related Javadoc.
    Code completion support provided in the editor
    You can also open the IDE's Javadoc window if you want continuous access to GWT documentation when working in the IDE. To do so, choose Window > Other > Javadoc from the main menu. Notice that when you type in the editor, the documentation in the Javadoc window updates according to your cursor's position.
    Javadoc window
  6. In the Projects window, right-click the project node and choose Run. This time, the label is shown with a custom style, using the stylesheet you created in this subsection.
    Stylesheet effects displayed in browser

Compiling and Debugging

Open the Files window (Ctrl-2; ⌘-2 on Mac) 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 the following:
Build folder displayed in Files window
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. For an explanation of what these files represent, see the Google Code FAQ - What's with all the cache/nocache stuff and weird filenames?.

Also, note that you can take advantage of the IDE's built-in debugger when working with GWT applications. This enables you to debug in GWT's hosted mode. The GWT and hosted mode main window and web browser open automatically.

Note for Mac OS X users: GWT's hosted mode is compiled for 32-bit architecture on Mac OS X, which exists only for Java 1.5. If you are running a 64-bit version of Java 1.6, you need to switch to a 32-bit version. You can do this using the Java Preferences panel in OS X. After switching Java versions, you should restart the IDE.

Set field, method and line breakpoints in your source files by clicking in the left margin of the IDE's editor.
Editor displaying a line breakpoint
Then simply choose Debug as you normally would for any web project (e.g., right-click the project node and choose Debug, or click the Debug Project icon ( Debug Project icon ). The application freezes on any breakpoint you set, allowing you to step through code and examine variable and expression values (e.g., Choose Window > Debugging > Local Variables to view values in the Local Variables window).
Debugger stopped at breakpoint
You can also hover over an expression or value in the editor, and the debugger uses a pop-up to inform you of the current value (as shown in the above image).
GWT's hosted mode main window and web browser open. The browser displays a running version of your application.
GWT hosted mode browser

Conclusion

In this tutorial, you have learned the following:

  • What a typical application source structure looks like in a Google Web Toolkit application.
  • How Google Web Toolkit artifacts relate to each other.
  • How to set up the IDE to use the Google Web Toolkit.
  • What the tools are that are available to you in the IDE, specifically for using the Google Web Toolkit.

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.


See Also

This concludes the Introduction to the Google Web Toolkit Framework tutorial. For related and more advanced material, see the following resources:

GWT Resources

NetBeans Documentation for Java Web Frameworks

get support for the NetBeans

Support


By use of this website, you agree to the NetBeans Policies and Terms of Use. © 2015, Oracle Corporation and/or its affiliates. Sponsored by Oracle logo