Playing through GWT with IntelliJ IDEA
This is the simple and at the same time bold promise of Googles Web Toolkit (GWT) on it’s relatively decent web housing on Google Code:
Developers can spend 90% of their time working around browser quirks. In addition, building, reusing, and maintaining large JavaScript code bases and AJAX components can be difficult and fragile. Google Web Toolkit (GWT), especially when combined with the Google Plugin for Eclipse, eases this burden by allowing developers to quickly build and maintain complex yet highly performant JavaScript front-end applications in the Java programming language.
As a first step of my personal convergence to this technology, I want to play through the official “StockWatcher” Getting Started Tutorial at their Website. I’m really curious, what I will like and what I maybe won’t like at all, especially when comparing my then freshly developed GWT awareness with the still cloudy but at the same time already demanding requirements I have in my mind with respect to Best-Of-Breed UI Technologies.
I don’t want to use Eclipse as suggested and recommended overthere, but IntelliJ IDEA, so maybe I can even deliver some additional value compared to the “official” tutorial. As Information about IDEAs GWT Support I found their 1-2-3 Video GWT Tutorial.
Step 1: Creating a GWT Project (Please see the Official Tutorial, too.)
- Install Google Web Toolkit
- Right Click on your IntelliJ IDEA Java Project.
- Select ‘Add Framework Support…’
- Check ‘Google Web Toolkit’ and select proper Installation Path
- Create a Java Package called ‘com.google.gwt.sample.stockwatcher’
- Right click your Package, select ‘New…/Google Web Toolkit/GWT Module’ and enter ‘StockWatcher’ as Name.
- Right click your Package, select ‘New…/Google Web Toolkit/GWT Remote Service’ and enter ‘Greeting’ as Name.
- If you happen to use Mac OS X, you must edit the Project Settings to use a Java 1.5 runtime for GWT Hosted Mode.
Step 2: Designing the Application Please see the Official Tutorial
Step 3: Building the User Interface (Please see the Official Tutorial, too.)
- Basically this Step consists of editing the StockWatcher Class (which means implementing an EntryPoint Interface):
public class StockWatcher implements EntryPoint { private VerticalPanel mainPanel = new VerticalPanel(); private FlexTable stocksFlexTable = new FlexTable(); private HorizontalPanel addPanel = new HorizontalPanel(); private TextBox newSymbolTextBox = new TextBox(); private Button addStockButton = new Button("Add"); private Label lastUpdatedLabel = new Label(); /** * Entry point method. */ public void onModuleLoad() { // Create table for stock data. stocksFlexTable.setText(0, 0, "Symbol"); stocksFlexTable.setText(0, 1, "Price"); stocksFlexTable.setText(0, 2, "Change"); stocksFlexTable.setText(0, 3, "Remove"); // Assemble Add Stock panel. addPanel.add(newSymbolTextBox); addPanel.add(addStockButton); // Assemble Main panel. mainPanel.add(stocksFlexTable); mainPanel.add(addPanel); mainPanel.add(lastUpdatedLabel); // Associate the Main panel with the HTML host page. RootPanel.get("stockList").add(mainPanel); // Move cursor focus to the input box. newSymbolTextBox.setFocus(true); } } - Once you have this you can already startup your “hosted” Test UI by right-clicking your StockWatcher Class and selecting ‘Run StockWatcher’. Once your ‘Hosted Mode Browser’ is running, it will reflect any Code Change you make after a Click on its ‘Refresh’ Button.
- One Remark: I had to increase my JRE heap size setting to 256MB first, by editing the Run/Edit Configurations (-Xmx256M) to get the Hosted Mode running.
Step 4: Managing Events on the Client Please see the Official Tutorial
Step 5: Coding Functionality on the Client Please see the Official Tutorial
Step 6: Managing Events on the Client (Please see the Official Tutorial, too.)
After having successfully added the EventListeners (Step 4), the required Table Coding (Step 5) and played through the quite convincing Debugging Section (Section 6), my Class looks now looks like the following:
public class StockWatcher implements EntryPoint {
private VerticalPanel mainPanel = new VerticalPanel();
private FlexTable stocksFlexTable = new FlexTable();
private HorizontalPanel addPanel = new HorizontalPanel();
private TextBox newSymbolTextBox = new TextBox();
private Button addStockButton = new Button("Add");
private Label lastUpdatedLabel = new Label();
private static final int REFRESH_INTERVAL = 5000; // ms
private ArrayList<String> stocks = new ArrayList<String>();
public void onModuleLoad() {
// Create table for stock data.
stocksFlexTable.setText(0, 0, "Symbol");
stocksFlexTable.setText(0, 1, "Price");
stocksFlexTable.setText(0, 2, "Change");
stocksFlexTable.setText(0, 3, "Remove");
// Assemble Add Stock panel.
addPanel.add(newSymbolTextBox);
addPanel.add(addStockButton);
// Assemble Main panel.
mainPanel.add(stocksFlexTable);
mainPanel.add(addPanel);
mainPanel.add(lastUpdatedLabel);
// Associate the Main panel with the HTML host page.
RootPanel.get("stockList").add(mainPanel);
// Move cursor focus to the input box.
newSymbolTextBox.setFocus(true);
// Setup timer to refresh list automatically.
Timer refreshTimer = new Timer() {
@Override
public void run() {
refreshWatchList();
}
};
refreshTimer.scheduleRepeating(REFRESH_INTERVAL);
// Listen for mouse events on the Add button.
addStockButton.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
addStock();
}
});
// Listen for keyboard events in the input box.
newSymbolTextBox.addKeyPressHandler(new KeyPressHandler() {
public void onKeyPress(KeyPressEvent event) {
switch (event.getCharCode()) {
case KeyCodes.KEY_ENTER: addStock();
}
}
});
}
private void addStock() {
final String symbol = newSymbolTextBox.getText()
.toUpperCase().trim();
newSymbolTextBox.setFocus(true);
// Stock code must be between 1 and 10 chars that
are numbers, letters, or dots.
if (!symbol.matches("^[0-9A-Z\\.]{1,10}$")) {
Window.alert("'" + symbol + "' is not a valid symbol.");
newSymbolTextBox.selectAll();
return;
}
newSymbolTextBox.setText("");
// Don't add the stock if it's already in the table.
if (stocks.contains(symbol))
return;
// Add the stock to the table.
int row = stocksFlexTable.getRowCount();
stocks.add(symbol);
stocksFlexTable.setText(row, 0, symbol);
// Add a button to remove this stock from the table.
Button removeStockButton = new Button("x");
removeStockButton.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
int removedIndex = stocks.indexOf(symbol);
stocks.remove(removedIndex);
stocksFlexTable.removeRow(removedIndex + 1);
}
});
stocksFlexTable.setWidget(row, 3, removeStockButton);
// TODO Get the stock price.
refreshWatchList();
}
private void refreshWatchList() {
final double MAX_PRICE = 100.0; // $100.00
final double MAX_PRICE_CHANGE = 0.02; // +/- 2%
StockPrice[] prices = new StockPrice[stocks.size()];
for (int i = 0; i < stocks.size(); i++) {
double price = Random.nextDouble() * MAX_PRICE;
double change = price * MAX_PRICE_CHANGE
* (Random.nextDouble() * 2.0 - 1.0);
prices[i] = new StockPrice(stocks.get(i), price, change);
}
updateTable(prices);
}
private void updateTable(StockPrice price) {
// Make sure the stock is still in the stock table.
if (!stocks.contains(price.getSymbol())) {
return;
}
int row = stocks.indexOf(price.getSymbol()) + 1;
// Format the data in the Price and Change fields.
String priceText = NumberFormat.getFormat("#,##0.00")
.format(price.getPrice());
NumberFormat changeFormat = NumberFormat
.getFormat("+#,##0.00;-#,##0.00");
String changeText = changeFormat.format(price.getChange());
String changePercentText = changeFormat
.format(price.getChangePercent());
// Populate the Price and Change fields with new data.
stocksFlexTable.setText(row, 1, priceText);
stocksFlexTable.setText(row, 2, changeText + " ("
+ changePercentText + "%)");
}
private void updateTable(StockPrice[] prices) {
for (int i = 0; i < prices.length; i++) {
updateTable(prices[i]);
}
// Display timestamp showing last refresh.
lastUpdatedLabel.setText("Last update : " + DateTimeFormat
.getMediumDateTimeFormat().format(new Date()));
}
}
In addition to that I have some encapsulated functionality in a new StockPrice class:
public class StockPrice {
private String symbol;
private double price;
private double change;
public StockPrice() {
}
public StockPrice(String symbol, double price, double change) {
this.symbol = symbol;
this.price = price;
this.change = change;
}
public String getSymbol() {
return this.symbol;
}
public double getPrice() {
return this.price;
}
public double getChange() {
return this.change;
}
public double getChangePercent() {
return 100.0 * this.change / this.price;
}
public void setSymbol(String symbol) {
this.symbol = symbol;
}
public void setPrice(double price) {
this.price = price;
}
public void setChange(double change) {
this.change = change;
}
}
Step 7: Applying Style (Please see the Official Tutorial, too.)
- CSS Stylesheets can be associated from within the HTML Host File or – preferably – from within the Module Definition XML:
<module> ... <inherits name="com.google.gwt.user.theme.dark.Dark"/> ... </module> - You can look up the name of the style rules (the CSS selector) for each widget by accessing the GWT API Reference via the Widget Gallery.
- Furthermore it’s possible to add custom HTML class names to the widgets and/or parts of it like e.g. Table Cells.



The URL to TrackBack this entry is: http://developing.schimak.at/2009/11/playing-through-gwt-with-intellij-idea/trackback/