Google Web Toolkit (GWT)
Google Web Toolkit (GWT)
What Is GWT?
An open-source, Java-based framework for creating Ajax web applications Created and used by Google Makes writing web applications similar to Swing applications
dramatically reduces the need to understand HTML and JavaScript maintaining Java code is easier than maintaining a mixture of HTML, JavaScript and Java code
Client-side code
compiled to HTML and JavaScript uses CSS for formatting restricted to a subset of Java 1.4 for now
Can throw Java exceptions from the server back to the client Can use Java IDEs like Eclipse, IDEA and NetBeans Created, maintained, enhanced and used by Google
recognized for their software expertise one of the few serious Microsoft competitors
Tool Support
IDE plugins
Intellij IDEA
GWT Studio
Eclipse
Cypal Studio for GWT ( was Googlipse) Instantiations GWT Designer
NetBeans
GWT4NB
Other tools
Wirelexsoft VistaFei - a GWT IDE
Installing
Steps
verify that a Java SDK (1.4 or higher) is installed
run java -version from a shell/command prompt
browse http://code.google.com/webtoolkit/ click the "Download Google Web Toolkit (GWT)" link download a platform-specific archive/zip file for a selected version unpackage the archive/zip file to a selected directory set the environment variable GWT_HOME to the path to the unpackaged GWT directory
Non-IDE steps
create a directory for the application from a shell/command prompt, navigate to that directory use the applicationCreator script to create the project directory structure and populate it with initial project files
under Windows, run
%GWT_HOME%\applicationcreator {package}.client.{module}
lib - holds JARs used by this project {package}.{module}.cache.html src {hash-code}.nocache.html package directories {hash-code}.nocache.xml module.gwt.xml client module.java entry point class service.java for a GWT RPC service serviceAsync.java other .java files to be compiled to JavaScript public module.html module.css images server - not automatically created serviceImpl.java other server-side only .java files tomcat - used by hosted mode embedded server
Minimal HTML
<html> <head> to find module XML <title>{title}</title> <meta name="gwt:module" content="{package}.{module}"> </head> bootstrap script loads <body> browser/local-specific JavaScript <script language="javascript" src="gwt.js"></script> <!-- OPTIONAL: include this if history support is desired --> <iframe id="__gwt_historyFrame" style="width:0;height:0;border:0"> </iframe> <!-- can add static HTML here --> </body> </html>
10
Widgets
11
Containers
12
Modules
GWT applications are referred to as modules A module has an XML descriptor, {module}.gwt.xml
can specify
inherited modules
to share custom widgets and other code
public paths
for locating CSS, JavaScript and image files
and more
stored in the source tree package directory just above entry point Java source file
13
For details on the content of module XML files, see http://code.google.com/webtoolkit/documentation/ com.google.gwt.doc.DeveloperGuide.Fundamentals.Modules.ModuleXml.html
14
CSS
GWT encourages formatting with CSS All widgets support these methods
addStyleName - adds to existing list of styles for the widget setStyleName - replaces existing list of styles for the widget
15
Event Handling
Most widgets support listening for user events
events generated by each widget differ
Listener interfaces
define methods that are invoked on objects that implement them (your code) when certain events occur for example, ClickListener often implemented by an anonymous inner class
like earlier example
Adapter classes
make it easier to implement listener interfaces by providing method implementations that do nothing, saving you the trouble of writing them only for interfaces with more than one method
16
LoadListener MouseListener
17
18
compile server-side Java code using a standard Java compiler GWTCompiler generates a separate JavaScript file for each supported browser and locale combination
the correct JavaScript file is automatically downloaded to the changing in GWT 1.4 requesting browser by the gwt.js bootstrap script this reduces the amount of JavaScript code that must be downloaded since only code applicable to that browser/locale is downloaded
continued on next page
19
deploy the WAR file to a JEE server such as Tomcat or JBoss run the application from a web browser by visiting http://{server}:{port}/{package}/{module}.html
20
10
Server Calls
Several forms are supported
HTML form submission XMLHttpRequest (classic Ajax) JavaScript Object Notation (JSON) GWT RPC
21
JavaScript code
22
11
Reusable modules
can be inherited by multiple GWT applications
Internationalization
using Java property files
23
More Information
Web pages
project homepage - http://code.google.com/webtoolkit/ developer guide - http://code.google.com/webtoolkit/documentation/ class doc. - http://code.google.com/webtoolkit/documentation/gwt.html OCI notes - http://www.ociweb.com/mark/programming/GWT.html
Mailing list
Google Group - http://groups.google.com/group/Google-Web-Toolkit
Blogs
Google Developer Blog - http://googlewebtoolkit.blogspot.com/ Robert Hanson (author of GWT In Action) - http://roberthanson.blogspot.com/
Podcasts
Java Posse GWT Round Table on 10/15/06
http://javaposse.com/index.php?post_id=140955
Books
none yet, but many on the way; see next page and
http://www.ociweb.com/mark/programming/GWT.html#Resources
Copyright 2007 by Object Computing, Inc. (OCI). All rights reserved.
Google Web Toolkit
24
12
25
Details
part outlined in red is a custom widget called DistanceWidget
contains a TextBox for entering a distance contains a ListBox for selecting units of Miles or Kilometers
changing selection converts the distance
26
13
add widgets to the FlexTable create VerticalPanel and use it to layout application title, FlexTable and Calculate button add VerticalPanel to RootPanel Additional Tasks: - add validation to the distance and add a ClickListener to Calculate button time TextBoxes that calculates pace and sets pace Label - add CSS to make the GUI look nicer
double miles = distanceWidget.getMiles(); String time = timeTextBox.getText(); String pace = Calculator.getMilePaceTime(miles, time); paceLabel.setText(pace); Copyright 2007 by Object Computing, Inc. (OCI). All rights reserved.
- add a KeyboardListener to the time TextBox so pressing Enter there is the same as pressing the Calculate button
27
28
14
Calculator.java
package com.ociweb.running.client; public class Calculator { private static final double KILOMETERS_PER_MILE = 1.609344; private static final double MILES_PER_KILOMETER = 1 / KILOMETERS_PER_MILE; public static double convertKilometersToMiles(double kilometers) { return kilometers * MILES_PER_KILOMETER; } public static double convertMilesToKilometers(double miles) { return miles * KILOMETERS_PER_MILE; }
29
Calculator.java (Contd)
/** * Converts a time string to the equivalent number of seconds. * Times must be in the format hh:mm:ss, mm:ss or ss. */ public static int convertTimeToSeconds(String time) { // Validate the time. String regex = "/(\\d{1,2})(:(\\d{1,2}))?(:(\\d{1,2}))?/"; if (matches(regex, time)) { throw new RuntimeException("Invalid time: " + time); } String[] pieces = time.split(":"); int count = pieces.length; int p0 = Integer.parseInt(pieces[0]); int p1 = count > 1 ? Integer.parseInt(pieces[1]) : 0; int p2 = count > 2 ? Integer.parseInt(pieces[2]) : 0; int hours = count == 3 ? p0 : 0; int minutes = count == 3 ? p1 : count == 2 ? p0 : 0; int seconds = count == 3 ? p2 : count == 2 ? p1 : p0; return (hours * 60 + minutes) * 60 + seconds; }
30
15
Calculator.java (Contd)
/** * Gets the minutes per mile pace time string * for a given distance (in miles) and total time. * Times must be in the format hh:mm:ss, mm:ss or ss. */ public static String getMilePaceTime(double miles, String time) { int seconds = convertTimeToSeconds(time); long secondsPerMile = Math.round(seconds / miles); double minutesPerMile = secondsPerMile / 60.0; int wholeMinutesPerMile = (int) Math.floor(minutesPerMile); long wholeSecondsPerMile = Math.round((minutesPerMile - wholeMinutesPerMile) * 60.0); String pace = wholeMinutesPerMile + ":"; if (wholeSecondsPerMile < 10) pace = '0' + pace; pace += wholeSecondsPerMile + " per mile"; return pace; }
31
Calculator.java (Contd)
/** * Gets the minutes per kilometer pace time string * for a given distance (in kilometers) * and total time. * Times must be in the format hh:mm:ss, mm:ss or ss. */ public static String getKilometerPaceTime( double kilometers, String time) { return getMilePaceTime(kilometers, time); } /** * Regular expression matching using JavaScript (JSNI). * @param regExp the regular expression * @param value the value to be compared * @return true if the value matches; false otherwise */ public native static boolean matches(String regExp, String value) /*-{ var pattern = new RegExp(regExp); return value.search(pattern) != -1; }-*/; }
32
16
DistanceWidget.java
package com.ociweb.running.client; import com.google.gwt.user.client.ui.*; import java.util.Map; import java.util.HashMap; public class DistanceWidget extends Composite { private static Map distanceMap = new HashMap(); private private private private ListBox distanceListBox = new ListBox(); ListBox unitListBox = new ListBox(); TextBox distanceTextBox = new TextBox(); int otherIndex;
public DistanceWidget() { setupDistanceTextBox(); setupUnitListBox(); setupDistanceListBox(); Panel panel = new HorizontalPanel(); panel.add(distanceTextBox); panel.add(unitListBox); panel.add(distanceListBox); initWidget(panel); }
Copyright 2007 by Object Computing, Inc. (OCI). All rights reserved.
33
DistanceWidget.java (Contd)
private void addDistance(String name, double distance) { distanceMap.put(name, new Double(distance)); if ("Other".equals(name)) otherIndex = distanceListBox.getItemCount(); distanceListBox.addItem(name); } private double getDistance(String name) { Double distance = (Double) distanceMap.get(name); return distance.doubleValue(); } public double getMiles() { double distance = Double.parseDouble(distanceTextBox.getText()); boolean isKilometers = unitListBox.getSelectedIndex() == 1; if (isKilometers) { distance = Calculator.convertKilometersToMiles(distance); } return distance; }
34
17
DistanceWidget.java (Contd)
private void setupDistanceListBox() { addDistance("Marathon", 26.2); addDistance("1/2 Marathon", 13.1); addDistance("10K", 10); addDistance("5K", 5); addDistance("Mile", 1); addDistance("Other", 0); distanceListBox.setSelectedIndex(0); distanceTextBox.setText(String.valueOf(getDistance("Marathon"))); distanceListBox.addChangeListener(new ChangeListener() { public void onChange(Widget sender) { int index = distanceListBox.getSelectedIndex(); String name = distanceListBox.getItemText(index); double distance = getDistance(name); String distanceText = distance == 0 ? "" : String.valueOf(distance); distanceTextBox.setText(distanceText); unitListBox.setSelectedIndex(name.endsWith("K") ? 1 : 0); } }); }
35
DistanceWidget.java (Contd)
private void setupDistanceTextBox() { distanceTextBox.setVisibleLength(5); distanceTextBox.addFocusListener(new ChangeListener () { public void onChange(Widget sender) { distanceListBox.setSelectedIndex(otherIndex); } }); }
36
18
DistanceWidget.java (Contd)
private void setupUnitListBox() { unitListBox.addItem("Miles"); unitListBox.addItem("Kilometers"); unitListBox.setSelectedIndex(0); unitListBox.addChangeListener(new ChangeListener() { public void onChange(Widget sender) { // Convert value in distanceTextBox to new unit. int index = unitListBox.getSelectedIndex(); String distanceText = distanceTextBox.getText(); double distance = Double.parseDouble(distanceText); distance = index == 0 ? Calculator.convertKilometersToMiles(distance) : Calculator.convertMilesToKilometers(distance); distanceTextBox.setText(String.valueOf(distance)); } }); } }
37
RunningCalc.java
package com.ociweb.running.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.user.client.ui.*; public class RunningCalc implements EntryPoint { private private private private private private Button calculateButton = new Button("Calculate"); DistanceWidget distanceWidget = new DistanceWidget(); Label paceLabel = new Label(); FlexTable table = new FlexTable(); TextBox timeTextBox = new TextBox(); int row = 0;
38
19
RunningCalc.java (Contd)
public void onModuleLoad() { timeTextBox.setText("2:57:11"); timeTextBox.setVisibleLength(10); timeTextBox.addKeyboardListener(new KeyboardListenerAdapter() { public void onKeyUp(Widget sender, char keyCode, int modifiers) { if (keyCode == KEY_ENTER) calculatePace(); } }); paceLabel.addStyleName("paceLabel"); calculateButton.addClickListener(new ClickListener() { public void onClick(Widget sender) { calculatePace(); } }); addRow("Distance:", distanceWidget); addRow("Time:", timeTextBox); addRow("Pace:", paceLabel);
39
RunningCalc.java (Contd)
VerticalPanel panel = new VerticalPanel(); Label titleLabel = new Label("Running Calculator"); titleLabel.addStyleName("title"); panel.add(titleLabel); panel.add(table); panel.add(calculateButton); RootPanel.get().add(panel); } private void addRow(String labelText, Widget widget) { Label label = new Label(labelText); label.addStyleName("tableLabel"); table.setWidget(row, 0, label); table.setWidget(row, 1, widget); row++; } private void calculatePace() { double miles = distanceWidget.getMiles(); String time = timeTextBox.getText(); String pace = Calculator.getMilePaceTime(miles, time); paceLabel.setText(pace); } }
Copyright 2007 by Object Computing, Inc. (OCI). All rights reserved.
40
20
RunningCalc.gwt.xml
<module> <inherits name='com.google.gwt.user.User'/> <entry-point class='com.ociweb.running.client.RunningCalc'/> </module>
41
RunningCalc.html
<html> <head> <title>RunningCalc Application</title> <meta name='gwt:module' content='com.ociweb.running.RunningCalc'> <link rel=stylesheet href="RunningCalc.css"> </head> <body> <script language="javascript" src="gwt.js"></script> <iframe id="__gwt_historyFrame style="width:0;height:0;border:0"></iframe> </body> </html>
42
21
RunningCalc.css
body { font-family: Comic Sans MS, sans-serif; font-size: small; margin: 8px; } .paceLabel { color: green; font-size: 10pt; font-weight: bold; } .tableLabel { color: purple; font-size: 12pt; font-weight: bold; text-align: right; } .title { color: blue; font-size: 18pt; font-weight: bold; }
43
Wrap-Up
GWT provides a way to leverage Java expertise and tools to build dynamic web applications without requiring knowledge of HTML, JavaScript and DOM manipulation CAIT may have a course on GWT soon Feel free to email questions about GWT to me at mark@ociweb.com Thanks for attending!
44
22