GWT auto generated application with source
While creating the GWT application GWT plugin will generate the "GWT Hello" auto generated source. That will gives you an idea about end-to-end GWT application. If you are new to GWT better first read about GWT and GWT plugin installation. In this page I am going to explain about the auto generated source with the source code.
While creating the project you have to select the generate automatic application source in the options. After creating the project, project folder structure looks like below,
In normal Java/JEE applications for UI we have used JSP's mostly. But, in GWT UI and Server source it should be in Java file only. The EntryPoint RootPanel loading will be happened by using an HTML/JSP file(Only one per module or project).
The GWT plugin under the project package it auto generate 3 other directories which contains the Client, Server and Shared files. Client directory contains the EntryPoint class along with the Service and ServiceAsync files. Service and ServiceAsync are two interface which acts as the GWT Controllers.
SampleGWT.java
package com.jtb.example.client; import com.jtb.example.shared.FieldVerifier; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.core.client.GWT; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.event.dom.client.KeyUpEvent; import com.google.gwt.event.dom.client.KeyUpHandler; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.DialogBox; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.VerticalPanel; /** * Entry point classes define <code>onModuleLoad()</code>. */ public class SampleGWT implements EntryPoint { /** * The message displayed to the user when the server cannot be reached or * returns an error. */ private static final String SERVER_ERROR = "An error occurred while " + "attempting to contact the server. Please check your network " + "connection and try again."; /** * Create a remote service proxy to talk to the server-side Greeting service. */ private final GreetingServiceAsync greetingService = GWT .create(GreetingService.class); /** * This is the entry point method. */ public void onModuleLoad() { final Button sendButton = new Button("Send"); final TextBox nameField = new TextBox(); nameField.setText("GWT User"); final Label errorLabel = new Label(); // We can add style names to widgets sendButton.addStyleName("sendButton"); // Add the nameField and sendButton to the RootPanel // Use RootPanel.get() to get the entire body element RootPanel.get("nameFieldContainer").add(nameField); RootPanel.get("sendButtonContainer").add(sendButton); RootPanel.get("errorLabelContainer").add(errorLabel); // Focus the cursor on the name field when the app loads nameField.setFocus(true); nameField.selectAll(); // Create the popup dialog box final DialogBox dialogBox = new DialogBox(); dialogBox.setText("Remote Procedure Call"); dialogBox.setAnimationEnabled(true); final Button closeButton = new Button("Close"); // We can set the id of a widget by accessing its Element closeButton.getElement().setId("closeButton"); final Label textToServerLabel = new Label(); final HTML serverResponseLabel = new HTML(); VerticalPanel dialogVPanel = new VerticalPanel(); dialogVPanel.addStyleName("dialogVPanel"); dialogVPanel.add(new HTML("<b>Sending name to the server:</b>")); dialogVPanel.add(textToServerLabel); dialogVPanel.add(new HTML("<br><b>Server replies:</b>")); dialogVPanel.add(serverResponseLabel); dialogVPanel.setHorizontalAlignment(VerticalPanel.ALIGN_RIGHT); dialogVPanel.add(closeButton); dialogBox.setWidget(dialogVPanel); // Add a handler to close the DialogBox closeButton.addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { dialogBox.hide(); sendButton.setEnabled(true); sendButton.setFocus(true); } }); // Create a handler for the sendButton and nameField class MyHandler implements ClickHandler, KeyUpHandler { /** * Fired when the user clicks on the sendButton. */ public void onClick(ClickEvent event) { sendNameToServer(); } /** * Fired when the user types in the nameField. */ public void onKeyUp(KeyUpEvent event) { if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) { sendNameToServer(); } } /** * Send the name from the nameField to the server and wait for a response. */ private void sendNameToServer() { // First, we validate the input. errorLabel.setText(""); String textToServer = nameField.getText(); if (!FieldVerifier.isValidName(textToServer)) { errorLabel.setText("Please enter at least four characters"); return; } // Then, we send the input to the server. sendButton.setEnabled(false); textToServerLabel.setText(textToServer); serverResponseLabel.setText(""); greetingService.greetServer(textToServer, new AsyncCallback<String>() { public void onFailure(Throwable caught) { // Show the RPC error message to the user dialogBox .setText("Remote Procedure Call - Failure"); serverResponseLabel .addStyleName("serverResponseLabelError"); serverResponseLabel.setHTML(SERVER_ERROR); dialogBox.center(); closeButton.setFocus(true); } public void onSuccess(String result) { dialogBox.setText("Remote Procedure Call"); serverResponseLabel .removeStyleName("serverResponseLabelError"); serverResponseLabel.setHTML(result); dialogBox.center(); closeButton.setFocus(true); } }); } } // Add a handler to send the name to the server MyHandler handler = new MyHandler(); sendButton.addClickHandler(handler); nameField.addKeyUpHandler(handler); } }
- The above file contains the UI source code with TextBox and Submit button.
- While clicking on the Submit button call the submitNameToServer() method. This will send name to server and retrieve the result from the server. If it is success it will call onSuccess() method or else onFailure() will show the error message.
GreetingService.java
package com.jtb.example.client; import com.google.gwt.user.client.rpc.RemoteService; import com.google.gwt.user.client.rpc.RemoteServiceRelativePath; /** * The client-side stub for the RPC service. */ @RemoteServiceRelativePath("greet") public interface GreetingService extends RemoteService { String greetServer(String name) throws IllegalArgumentException; }
GreetingServiceAsync.java
package com.jtb.example.client; import com.google.gwt.user.client.rpc.AsyncCallback; /** * The async counterpart of <code>GreetingService</code>. */ public interface GreetingServiceAsync { void greetServer(String input, AsyncCallback<String> callback) throws IllegalArgumentException; }
- GreetingService and GreetinServiceAsync are two interfaces which are interlinking to send request and receive response.
- The annotation @RemoteServiceRelativePath will help's to call the respective servlet in the server source.
- The below source will show's how to generate the instance of these interfaces to call respective method.
private final GreetingServiceAsync greetingService = GWT.create(GreetingService.class); greetingService.greetServer(textToServer,new AsyncCallback<String>() { public void onFailure(Throwable caught) { ...... } public void onSuccess(String result) { ....... } }
GreetingServiceImpl.java
package com.jtb.example.server; import com.jtb.example.client.GreetingService; import com.jtb.example.shared.FieldVerifier; import com.google.gwt.user.server.rpc.RemoteServiceServlet; /** * The server-side implementation of the RPC service. */ @SuppressWarnings("serial") public class GreetingServiceImpl extends RemoteServiceServlet implements GreetingService { public String greetServer(String input) throws IllegalArgumentException { // Verify that the input is valid. if (!FieldVerifier.isValidName(input)) { // If the input is not valid, throw an IllegalArgumentException back to // the client. throw new IllegalArgumentException( "Name must be at least 4 characters long"); } String serverInfo = getServletContext().getServerInfo(); String userAgent = getThreadLocalRequest().getHeader("User-Agent"); // Escape data from the client to avoid cross-site script vulnerabilities. input = escapeHtml(input); userAgent = escapeHtml(userAgent); return "Hello, " + input + "!<br><br>I am running " + serverInfo + ".<br><br>It looks like you are using:<br>" + userAgent; } /** * Escape an html string. Escaping data received from the client helps to * prevent cross-site script vulnerabilities. * * @param html the html string to escape * @return the escaped string */ private String escapeHtml(String html) { if (html == null) { return null; } return html.replaceAll("&", "&").replaceAll("<", "<") .replaceAll(">", ">"); } }
- This is the server file named as GreetingServiceImpl and it implements the RemoteServiceServlet along with the GreetingService interface.
- RemoteServiceServlet helps to GWT RPC(Remote Procedure Call) to call specific Service method remotely.
- All service methods implementation should be written in ServiceImpl classes which located file under the server directory.
FieldVerifier.java
package com.jtb.example.shared; /** * <p> * FieldVerifier validates that the name the user enters is valid. * </p> * <p> * This class is in the <code>shared</code> package because we use it in both * the client code and on the server. On the client, we verify that the name is * valid before sending an RPC request so the user doesn't have to wait for a * network round trip to get feedback. On the server, we verify that the name is * correct to ensure that the input is correct regardless of where the RPC * originates. * </p> * <p> * When creating a class that is used on both the client and the server, be sure * that all code is translatable and does not use native JavaScript. Code that * is not translatable (such as code that interacts with a database or the file * system) cannot be compiled into client-side JavaScript. Code that uses native * JavaScript (such as Widgets) cannot be run on the server. * </p> */ public class FieldVerifier { /** * Verifies that the specified name is valid for our service. * * In this example, we only require that the name is at least four * characters. In your application, you can use more complex checks to ensure * that usernames, passwords, email addresses, URLs, and other fields have the * proper syntax. * * @param name the name to validate * @return true if valid, false if invalid */ public static boolean isValidName(String name) { if (name == null) { return false; } return name.length() > 3; } }
- FieldVerifier class is used for field validation.
- As per the above validation name field contains the at least 4 characters in the TextField.
- If it contains less than 4 characters as per the validation it should not allow the further.
SampleGWT.gwt.xml:
<?xml version="1.0" encoding="UTF-8"?> <!-- When updating your version of GWT, you should also update this DTD reference, so that your app can take advantage of the latest GWT module capabilities. --> <!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.6.0//EN" "http://google-web-toolkit.googlecode.com/svn/tags/2.6.0/distro-source/core/src/gwt-module.dtd"> <module rename-to='samplegwt'> <!-- Inherit the core Web Toolkit stuff. --> <inherits name='com.google.gwt.user.User'/> <!-- Inherit the default GWT style sheet. You can change --> <!-- the theme of your GWT application by uncommenting --> <!-- any one of the following lines. --> <inherits name='com.google.gwt.user.theme.clean.Clean'/> <!-- <inherits name='com.google.gwt.user.theme.standard.Standard'/> --> <!-- <inherits name='com.google.gwt.user.theme.chrome.Chrome'/> --> <!-- <inherits name='com.google.gwt.user.theme.dark.Dark'/> --> <!-- Other module inherits --> <!-- Specify the app entry point class. --> <entry-point class='com.jtb.example.client.SampleGWT'/> <!-- Specify the paths for translatable code --> <source path='client'/> <source path='shared'/> <!-- allow Super Dev Mode --> <add-linker name="xsiframe"/> </module>
- This is the file which will contains the EntryPoint, inherits and source directories.
- In future if you have used GXT along with GWT you must and should declare the respective inherit.
- add-linker tag contains the xsiframe which will be included in gwt-2.5.1 onwards. This will helps to run your application in "Super Development Mode".
web.xml:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"> <!-- Servlets --> <servlet> <servlet-name>greetServlet</servlet-name> <servlet-class>com.jtb.example.server.GreetingServiceImpl</servlet-class> </servlet> <servlet-mapping> <servlet-name>greetServlet</servlet-name> <url-pattern>/samplegwt/greet</url-pattern> </servlet-mapping> <!-- Default page to serve --> <welcome-file-list> <welcome-file>SampleGWT.html</welcome-file> </welcome-file-list> </web-app>
- The deployment descriptor contains the servlet and servlet mapping along with welcome file.
- This is the file which will decide which servlet has to call.
SampleGWT.html
<!doctype html> <!-- The DOCTYPE declaration above will set the --> <!-- browser's rendering engine into --> <!-- "Standards Mode". Replacing this declaration --> <!-- with a "Quirks Mode" doctype is not supported. --> <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <!-- --> <!-- Consider inlining CSS to reduce the number of requested files --> <!-- --> <link type="text/css" rel="stylesheet" href="SampleGWT.css"> <!-- --> <!-- Any title is fine --> <!-- --> <title>Web Application Starter Project</title> <!-- --> <!-- This script loads your compiled module. --> <!-- If you add any GWT meta tags, they must --> <!-- be added before this line. --> <!-- --> <script type="text/javascript" language="javascript" src="samplegwt/samplegwt.nocache.js"></script> </head> <!-- --> <!-- The body can have arbitrary html, or --> <!-- you can leave the body empty if you want --> <!-- to create a completely dynamic UI. --> <!-- --> <body> <!-- OPTIONAL: include this if you want history support --> <iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe> <!-- RECOMMENDED if your web app will not function without JavaScript enabled --> <noscript> <div style="width: 22em; position: absolute; left: 50%; margin-left: -11em; color: red; background-color: white; border: 1px solid red; padding: 4px; font-family: sans-serif"> Your web browser must have JavaScript enabled in order for this application to display correctly. </div> </noscript> <h1>Web Application Starter Project</h1> <table align="center"> <tr> <td colspan="2" style="font-weight:bold;">Please enter your name:</td> </tr> <tr> <td id="nameFieldContainer"></td> <td id="sendButtonContainer"></td> </tr> <tr> <td colspan="2" style="color:red;" id="errorLabelContainer"></td> </tr> </table> </body> </html>
- In the HTML file Script tag will be helped to enable JavaScript. By mistake if script tag is commented GWT application might not be load properly.
- TD tag ID's should be matched in the EntryPoint RootPanel values.
SampleGWT.css
/** Add css rules here for your application. */ /** Example rules used by the template application (remove for your app) */ h1 { font-size: 2em; font-weight: bold; color: #777777; margin: 40px 0px 70px; text-align: center; } .sendButton { display: block; font-size: 16pt; } /** Most GWT widgets already have a style name defined */ .gwt-DialogBox { width: 400px; } .dialogVPanel { margin: 5px; } .serverResponseLabelError { color: red; } /** Set ids using widget.getElement().setId("idOfElement") */ #closeButton { margin: 15px 6px 6px; }
- CSS will be applied on TextBox, Button, Grid... by using the addStyleName() method.