For some months ago I’ve created a small guestbook web application in Google Web Toolkit (GWT). It’s deployed to Googles Appspot:
http://awt-guestbook.appspot.com/
The web application is written in Java and HTML. On compilation the Java code is transformed into JavaScript. Here is some source code example from the application:
Guestbook.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<link type="text/css" rel="stylesheet" href="Guestbook.css">
<title>GWT Guestbook</title>
<script type="text/javascript" language="javascript" src="guestbook/guestbook.nocache.js"></script>
</head>
<body>
<iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe>
<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>GWT Guestbook</h1>
<div id="errorBox"></div>
<h3>Post a new guestbook entry:</h3>
<div id="nameFieldContainer">Name: </div>
<div id="messageFieldContainer"></div>
<div id="sendButtonContainer"></div>
<h3>Guestbook entries:</h3>
<div id="entriesLoading"></div>
<div id="entries"></div>
</body>
</html>
client/Guestbook.java
package awt.example.guestbook.client;
import java.util.*;
import com.google.gwt.user.client.Timer;
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.*;
/**
* Entry point classes define <code>onModuleLoad()</code>.
*/
public class Guestbook implements EntryPoint {
private long newestEntryTime = 0;
private Label labelError;
private Label labelLoading;
private VerticalPanel entryPanel = new VerticalPanel();
/**
* Create a remote service proxy to talk to the server-side Guestbook
* service.
*/
private final GuestbookServiceAsync guestbookService = GWT
.create(GuestbookService.class);
/**
* This is the entry point method.
*/
public void onModuleLoad() {
// creating a error message
this.labelError = new Label(
"An error occured while processing your request");
this.labelError.addStyleName("error");
this.labelError.setVisible(false);
RootPanel.get("errorBox").add(this.labelError);
// creating loading message
this.labelLoading = new Label("Loading guestbook entries..");
this.labelLoading.addStyleName("loading");
RootPanel.get("entriesLoading").add(this.labelLoading);
// adding entryPanel to HTML
RootPanel.get("entries").add(this.entryPanel);
// creating other buttons
final Button buttonSend = new Button("Post");
final TextBox fieldName = new TextBox();
final TextArea fieldMessage = new TextArea();
fieldMessage.setPixelSize(300, 100);
fieldName.setStyleName("inputField");
fieldMessage.setStyleName("inputField");
buttonSend.addStyleName("submitButton");
// Add the nameField and sendButton to the RootPanel
// Use RootPanel.get() to get the entire body element
RootPanel.get("nameFieldContainer").add(fieldName);
RootPanel.get("messageFieldContainer").add(fieldMessage);
RootPanel.get("sendButtonContainer").add(buttonSend);
// Focus the cursor on the name field when the app loads
fieldMessage.setFocus(true);
fieldMessage.selectAll();
// 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) {
sendEntryToServer();
}
/**
* Fired when the user types in the nameField.
*/
public void onKeyUp(KeyUpEvent event) {
if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
sendEntryToServer();
}
}
/**
* Send the guestbookEntry to the server and wait for a response.
*/
private void sendEntryToServer() {
buttonSend.setEnabled(false);
GuestbookEntryDTO entry = new GuestbookEntryDTO(fieldName
.getText(), fieldMessage.getText());
guestbookService.addEntry(entry, new AsyncCallback<String>() {
public void onFailure(Throwable caught) {
showError();
buttonSend.setEnabled(true);
}
public void onSuccess(String result) {
fieldName.setValue("");
fieldMessage.setValue("");
buttonSend.setEnabled(true);
updateEntries();
}
});
}
}
// Add a handler to send the name to the server
MyHandler handler = new MyHandler();
buttonSend.addClickHandler(handler);
fieldName.addKeyUpHandler(handler);
fieldMessage.addKeyUpHandler(handler);
// creating timer to look for new guestbook entries
Timer refreshTimer = new Timer() {
@Override
public void run() {
updateEntries();
}
};
refreshTimer.scheduleRepeating(5000);
// getting all entries
getEntries();
}
private void getEntries() {
guestbookService
.getEntries(new AsyncCallback<List<GuestbookEntryDTO>>() {
public void onFailure(Throwable caught) {
showError();
}
public void onSuccess(List<GuestbookEntryDTO> entries) {
labelLoading.setVisible(false);
for (GuestbookEntryDTO entry : entries) {
displayEntry(entry);
}
}
});
}
private void updateEntries() {
guestbookService.getEntries(this.newestEntryTime,
new AsyncCallback<List<GuestbookEntryDTO>>() {
public void onFailure(Throwable caught) {
showError();
}
public void onSuccess(List<GuestbookEntryDTO> entries) {
for (GuestbookEntryDTO entry : entries) {
displayEntry(entry);
}
}
});
}
private void displayEntry(GuestbookEntryDTO entry) {
String date = convertTimeToDate(entry.getTime());
HTML widget = new HTML("<div class='entry'><strong>" + entry.getName()
+ "</strong> - " + date + "<br> " + entry.getMessage()
+ "</div>");
this.entryPanel.insert(widget, 0);
if (entry.getTime() > newestEntryTime) {
newestEntryTime = entry.getTime();
}
}
private void showError() {
this.labelError.setVisible(true);
}
private String convertTimeToDate(long time) {
Date tmpDate = new Date();
tmpDate.setTime(time);
return tmpDate.toString();
}
}
server/GuestbookServiceImpl.java
package awt.example.guestbook.server;
import java.util.*;
import awt.example.guestbook.client.*;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
/**
* The server side implementation of the RPC service.
*/
@SuppressWarnings("serial")
public class GuestbookServiceImpl extends RemoteServiceServlet implements
GuestbookService {
private List<GuestbookEntryDTO> messages = new ArrayList<GuestbookEntryDTO>();
public String addEntry(GuestbookEntryDTO entry) {
messages.add(entry);
return null;
}
public List<GuestbookEntryDTO> getEntries() {
return this.messages;
}
public List<GuestbookEntryDTO> getEntries(long timeAfter) {
List<GuestbookEntryDTO> resMessages = new ArrayList<GuestbookEntryDTO>();
for (GuestbookEntryDTO entry : this.messages) {
if (entry.getTime() > timeAfter)
resMessages.add(entry);
}
return resMessages;
}
}
If you don’t know how to set up GWT in Eclipse follow this tutorial from Google:
http://code.google.com/webtoolkit/usingeclipse.html
Download
Download the complete GWT sample project (Eclipse)
Download GWT Guestbook Eclipse project
Please feel free to leave a comment below.