Google’s Stockwatcher Example

July 10, 2010 at 2:22 pm 1 comment

This tutorial introduces the fundamentals of a Google Web Toolkit (GWT) application by walking you through the creation of a simple stock watch list that we’ll call “StockWatcher”.

The module descriptor file (Stockwatcher.gwt.xml)

  • located in src folder package
    • com.google.gwt.sample.stockwatcher
<module>
<!-- 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.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.google.gwt.sample.stockwatcher.client.StockWatcher'/>
<!-- Specify the application specific style sheet.              -->
<stylesheet src='StockWatcher.css' /></module>

Client : directory will contain all of our client-side source files and any subpackages

  public void onModuleLoad() {
    Image img = new Image("http://code.google.com/webtoolkit/logo-185x175.png");
    Button button = new Button("Click me");

    // We can add style names
    button.addStyleName("pc-template-btn");
    // or we can set an id on a specific element for styling
    img.getElement().setId("pc-template-img");

    VerticalPanel vPanel = new VerticalPanel();
    vPanel.setWidth("100%");
    vPanel.setHorizontalAlignment(VerticalPanel.ALIGN_CENTER);
    vPanel.add(img);
    vPanel.add(button);

    // Add image and button to the RootPanel
    RootPanel.get().add(vPanel);

    // Create the dialog box
    final DialogBox dialogBox = new DialogBox();
    dialogBox.setText("Welcome to GWT!");
    dialogBox.setAnimationEnabled(true);
    Button closeButton = new Button("close");
    VerticalPanel dialogVPanel = new VerticalPanel();
    dialogVPanel.setWidth("100%");
    dialogVPanel.setHorizontalAlignment(VerticalPanel.ALIGN_CENTER);
    dialogVPanel.add(closeButton);

    closeButton.addClickListener(new ClickListener() {
      public void onClick(Widget sender) {
        dialogBox.hide();
      }
    });

    // Set the contents of the Widget
    dialogBox.setWidget(dialogVPanel);

    button.addClickListener(new ClickListener() {
      public void onClick(Widget sender) {
        dialogBox.center();
        dialogBox.show();
      }

Public – directory is a repository for any static resources that we need to include with our GWT application

  • Stockwatcher.css
    • This file is referenced in the descriptor file
  • Stockwatcher.html
    • the application’s host page. A host page is the container for a GWT application. It’s a regular HTML file that contains a <script> tag pointing to your application’s startup script.
<script type="text/javascript" language="javascript"
src="com.google.gwt.sample.stockwatcher.StockWatcher.nocache.js">
</script>

The GWT User Interface

  1. Widgets – allow you to interact with the user
  2. Panels – control the placement user interface elements on the page
    • RootPanel -top of any GWT user interface hierarchy
      default RootPanel wraps the HTML host page’s <body> element.
    • Vertical Panel
  3. Button – A standard push-button widget.
    • Button -extends ButtonBase
      Button button = new Button(“Click me”);
  4. Dialog Box – A form of popup that has a caption area at the top and can be dragged by the user.
  5. Click Listener – onclick method fired when the user clicks on a widget.
  6. Keyboard Listener – Event listener interface for keyboard events.
  7. Flex Table – A flexible table that creates cells on demand. Multiple rows or columns.
  8. Text Box – single line of input of text

AJAX applications, on the other hand, offload the user interface logic to the client and make asynchronous remote procedure calls to the server to send and receive only the data itself. This allows your application’s UI to be much more responsive and fluid while reducing the bandwidth requirements and the load on your server. All GWT applications run as JavaScript code in the end user’s web browser.

The GWT RPC framework makes it easy for the client and server components of your web application to exchange Java objects over HTTP.

The server-side code that gets invoked from the client is often referred to as a service.

The implementation of a GWT RPC service

which runs on the server is based on :

  • the well-known Java servlet architecture
  • create a class that implements the service interface. It also needs to extend the RemoteServiceServlet class
  • since on the server can use java.util.Random
  • add a <servlet> element to your module’s XML file pointing to the implementation class
<servlet path="/stockPrices" class=
"com.google.gwt.sample.stockwatcher.server.StockPriceServiceImpl" />

Asynchronous calls

All RPC calls you make in GWT are asynchronous, which means they don’t block while waiting for the call to return. There are several benefits to using that approach instead of simpler, synchronous (blocking) calls.

Since an async call invocation does not block, the code following the call executes immediately. When the call completes, it will run code within a callback method you specified when you made the call.

The way you specify your callback methods is by : passing an AsyncCallback object to the service proxy class when you invoke one of the service’s methods.

The callback object must contain two methods:

  • onFailure(Throwable)
  • onSuccess(T).

When the server call completes, one of these two methods will be called depending on whether the call succeeded or failed.

If the call completes successfully, the return value will show up as a parameter to our onSuccess(T) callback method.
To add an AsyncCallback parameter to all of our service methods :

  • we’re going to have to create a new interface with new method definitions. This asynchronous version will be very similar to the original service interface, with a few important differences.
    • It must have the same name as the service interface, with an Async added to the end.
    • It must be located in the same package as the service interface
    • Each method must have the same name and signature as the service interface, except with no return type and an AsyncCallback object as the last parameter.
package com.google.gwt.sample.stockwatcher.client;
import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;
@RemoteServiceRelativePath("stockPrices")
public interface StockPriceService extends RemoteService {
	StockPrice[] getPrices(String[] symbols);
}
package com.google.gwt.sample.stockwatcher.client;
import com.google.gwt.user.client.rpc.AsyncCallback;
public interface StockPriceServiceAsync {
	void getPrices(String[] symbols,
			       AsyncCallback<StockPrice[]> callback);
}

Steps to call the RPC service from the client

Create the service proxy class

Set up the callback

  • Create a new instance of an AsyncCallback object.
  • When the RPC call completes, if all goes well:
    • our onSuccess(T) will be called
  • we’ll receive the return value as the result argument.
  • If something goes wrong with the call:
    • GWT will call our onFailure(Throwable) method, passing us the exception:
AsyncCallback <StockPrice[]> callback = new AsyncCallback<StockPrice[]>() {
         public void onFailure(Throwable caught) {
           // do something with errors  }
         public void onSuccess(StockPrice[] result) {
          // update the watch list FlexTable  }
};

Make the call

  • All that’s left now is to actually make the call:
    • stockPriceSvc.getPrices(symbols, callback);
package com.google.gwt.sample.stockwatcher.client;
...

public class StockWatcher implements EntryPoint {
...
// create for server impl
private StockPriceServiceAsync stockPriceSvc;
...
private void refreshWatchList() {
// lazy initialization of service proxy 

if (stockPriceSvc == null) {
	stockPriceSvc = GWT.create(StockPriceService.class);
}
AsyncCallback<StockPrice[]> callback = new AsyncCallback<StockPrice[]>() {
	public void onFailure(Throwable caught) {
				// do something with errors
	}
	public void onSuccess(StockPrice[] result) {
		updateTable(result);
	}
};
	// make the call to the stock price service
	stockPriceSvc.getPrices(stocks.toArray(new String[0]), callback);
}

GWT Serializatiion

Anytime you transfer an object over the network via GWT RPC, it needs to be serialized.

Serialization is the process of packaging the contents of an object so that it can moved from one application to another application or stored for later use.

GWT RPC requires that all service method parameters and return types be serializable.

Note that although the two are similar:

  • GWT serialization is not the same as serialization based on the Java Serializable interface.

Serialization requirements So what makes a type serializable? To start with, all primitive types (int, char, boolean, etc.) and their wrapper objects are serializable by default.

Arrays of serializable types are also by extension serializable.

Classes are serializable if they meet a few basic requirements:

  • It implements IsSerializable or Serializable, either directly or because it derives from a superclass that does.
  • Its non-final, non-transient instance fields are themselves serializable, and

It has a default (zero argument) constructor with any access modifier (e.g. private Foo(){} will work)

package com.google.gwt.sample.stockwatcher.client;

import com.google.gwt.user.client.rpc.IsSerializable;

//public class StockPrice
public class StockPrice implements IsSerializable{
...
Advertisements

Entry filed under: Uncategorized.

Hello World Gin! GWT TestCase

1 Comment Add your own

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Trackback this post  |  Subscribe to the comments via RSS Feed


@davidmbloom


%d bloggers like this: