Thursday, June 25, 2009

Flex Chart inside GWT Page


Hello All, Today i want to talk about getting GWT to Work with Flex Charts.

We are going to tackle this from two sides. We will first talk about creating simple Flex Chart and then we will embed that in to GWT module.

In order to create a simple Flex Chart you would be needing Flex Builder from Adobe. You can download latest trial version from here. Flex Builder is built on eclipse platform, so if you are comfortable with eclipse, you should feel comfortable with Flex Builder. When i evaluated it, it only took me an hour to get familiar with.

Once you have it up an running, Create new Flex Project from File-> New-> Flex Project.

This will create a sample .mxml file, this is basically where you code your flex Chart.

I am first going to spit the content for .mxml file and then our Gwt Module to access this chart.

Note : As my intention here is to talk about GWT and show how Flex Chart can be used with GWT. So i am not going to explain this code below in detail, Just Play closer attention to Highlighted code.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="horizontal" styleName="myApplication" xmlns:ns1="bridge.*">
<mx:Script>
<![CDATA[
import mx.collections.*;
<!-- [Bindable] basically is saying we are binding the variable below to some component. In our case its Column Chart -->
[Bindable]
public var stateArray:ArrayCollection;

public function initData():void {
stateArray=new ArrayCollection( [
{ Profit: getRandomUint(100), Expenses: getRandomUint(10) },
{ Profit: getRandomUint(100), Expenses: getRandomUint(10) },
{ Profit: getRandomUint(100), Expenses: getRandomUint(10) } ]);
}
private function getRandomUint(max:uint):uint {
return Math.round(Math.random() * max);
}

]]>
</mx:Script>
<!-- Define custom colors for use as plot point fills. -->
<mx:SolidColor id="sc1" color="blue" alpha=".3"/>
<mx:SolidColor id="sc2" color="red" alpha=".3"/>
<mx:SolidColor id="sc3" color="green" alpha=".3"/>


<!-- Define custom Strokes. -->
<mx:Stroke id="s1" color="blue" weight="1"/>
<mx:Stroke id="s2" color="red" weight="1"/>
<mx:Stroke id="s3" color="green" weight="1"/>

<mx:SeriesSlide
id="slideIn"
duration="1000"
direction="up"
/>
<mx:SeriesSlide
id="slideOut"
duration="1000"
direction="down"
/>
<mx:SeriesInterpolate
id="interpol"
duration="1000"
elementOffset="0"
minimumElementDuration="200"
/>

<mx:ApplicationControlBar dock="true">
<mx:Button label="Change Data"
click="initData();" />
</mx:ApplicationControlBar>

<mx:ColumnChart name="columnchart" x="73" y="55" id="columnchartid" width="519" height="211" dataProvider="{stateArray}">
<mx:series>
<mx:ColumnSeries displayName="Plot 1" yField="Profit" xField="Expenses" fill="{sc1}" stroke="{s1}" showDataEffect="{slideIn}"
hideDataEffect="{slideOut}"/>
</mx:series>
</mx:ColumnChart>
<ns1:FABridge/>
</mx:Application>

When you execute above code in flex builder from Run Menu, it will create bunch of files. Couple that we are interested are .mxml and .swf, copy them in to your GWT module that you are creating. Refer to my previous post on how to create a basic GWT Module.

Now Lets see what goes in to GWT Module.

In order to use Flex Charts, you would basically need to use gwt-fabrdge.jar, this internally depends on gwt2swf-0.6.0.jar, Add them to your GWT module Classpath.

Lets first list out package structure and then i will explain in detail.

com/gwtbasics/gwtflex/gwtFlash.gwt.xml
com/gwtbasics/gwtflex/public/flexChart.mxml
com/gwtbasics/gwtflex/public/flexChart.swf
com/gwtbasics/gwtflex/client/GwtFlexModule.java
war/flexCharts.html

First lets talk gwtFlash.gwt.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 1.7.0//EN" "http://google-web-toolkit.googlecode.com/svn/tags/1.7.0/distro-source/core/src/gwt-module.dtd">
<module rename-to='gwtflex'>
<inherits name='com.google.gwt.user.User' />
<inherits name="pl.rmalinowski.gwt2swf.GWT2SWF"/>
<inherits name='org.argunet.gwt.fabridge.FABridge' />

<!-- Specify the app entry point class. -->
<entry-point class='com.gwtbasics.gwtflex.client.GwtFlexModule'/>
</module>
Most important is that the module inherits two packages namely GWT2SWF and FABridge.

Next in list is GwtGlexModule.java
package com.gwtbasics.gwtflex.client;

import org.argunet.gwt.fabridge.client.SWFABridgeWidget;

import pl.rmalinowski.gwt2swf.client.ui.SWFSettings;
import pl.rmalinowski.gwt2swf.client.utils.PlayerVersion;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.VerticalPanel;

public class GwtFlexModule implements EntryPoint {
public void onModuleLoad() {
SWFSettings swfSettings = new SWFSettings();
swfSettings.setMinPlayerVersion(new PlayerVersion(9,0,124));
SWFABridgeWidget swfbridge = new SWFABridgeWidget("gwtflex/flexChart.swf", 800, 500, swfSettings, "sample");
swfbridge.setVisible(true);
VerticalPanel outer = new VerticalPanel();
outer.add(swfbridge);
RootPanel.get("flexChartWidget").add(outer);
}
}
All we need now is the html file to call this GWT module.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<style type="text/css">
h1 {
font-size: 2em;
font-weight: bold;
color: #777777;
margin: 40px 0px 70px;
text-align: center;
}
</style>
<title>Flex GWT Module Demo Starter Project</title>
<script type="text/javascript" language="javascript" src="gwtflex/gwtflex.nocache.js"></script>
</head>
<body>
<h1>Simple Column Chart from Flex</h1>
<div align=" center" id="statusLabel"></div>
<div align=" center" id="flexChartWidget"></div>
</body>
</html>

For this example you need to get gwtflex/gwtflex.nocache.js that gets created when you compile using GWT compiler.

If you are using Google Plugin for Eclipse, just right click on the project and run/debug as Web Application and you will see the result.
But if you have generated your application through webAppCreator, you can use ant build.xml to execute. Execute hosted
ant task to invoke your app in hosted mode.

I hope you were able to successfully used flex chart inside GWT Page and enjoyed the experience of it.

Please stay tuned to my blog for more advanced implementation of GWT Flex Integration. In next Blog i will talk about passing dynamic content to Flex Chart from GWT Application.

Friday, June 12, 2009

Google Maps Api With GWT


Today i am going to demonstrate how to use google maps Api with GWT.
To get your hands free, i am going to show a simple map with an address plotted on it.


On the left you are seeing the snapshot of what we are trying to achieve. It surely don't look pretty. My intention is concentrate more on its functionality and how it can be achieved.

Let us start writing code directly, If you already don't have the GWT environment setup, Please refer to my GWT Basics post on how to set up your GWT application.

I order for you to use google api, you need to have gwt-maps-1.0.4.jar(get it here) along with gwt-user.jar and gwt-dev-{OS}.jar (refer to my GWT Basics post for detail explanation on gwt-dev-{OS}.jar)

Now that you got the environment set up, shall we start coding? I will take that as Yes then.

Lets first list out the files we are going to create and then i will talk in detail about each one.

com/gwtbasics/gmaps/gmaps.gwt.xml
com/gwtbasics/gmaps/client/GMapsModule.java
war/WEB-INF/gmaps.html

I will first explian GMapsModule.java EntryPoint. Give a closer look a the highlighted code for better understanding.
package com.gwtbasics.gmaps.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.maps.client.InfoWindowContent;
import com.google.gwt.maps.client.MapWidget;
import com.google.gwt.maps.client.geocode.Geocoder;
import com.google.gwt.maps.client.geocode.LatLngCallback;
import com.google.gwt.maps.client.geom.LatLng;
import com.google.gwt.maps.client.overlay.Marker;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.VerticalPanel;

public class GMapsModule implements EntryPoint {

public void onModuleLoad() {
final MapWidget map = new MapWidget(LatLng.newInstance(0, 0), 12);
final Label statusLabel = new Label();

VerticalPanel outer = new VerticalPanel();
map.setDoubleClickZoom(true);
map.setDraggable(true);
outer.add(map);
map.setSize("500px", "300px");
map.setGoogleBarEnabled(true);

LatLngCallback callback = new LatLngCallback() {

public void onFailure() {
statusLabel.setText("Address was Not Found");
}

public void onSuccess(LatLng point) {
statusLabel.setText("Address was Found");
Marker marker = new Marker(point);
map.addOverlay(marker);
map.setCenter(point);
VerticalPanel panel = new VerticalPanel();
InfoWindowContent content = new InfoWindowContent(panel);
panel.add(new Label("Voila Google Found me !!!"));
map.getInfoWindow().open(marker, content);
}
};
Geocoder geocoder = new Geocoder();
geocoder.getLatLng("dallas downtown", callback);

RootPanel.get("statusLabel").add(statusLabel);
RootPanel.get("mapWidget").add(outer);

}

}



Now lets talk about highlighted code.

final MapWidget map = new MapWidget(LatLng.newInstance(0, 0), 12);
Here we are creating an instance to MapWidget which takes an instance LatLng instance and default zoom level. I just created LatLng with (0,0), As i dont know the latitude and longitude values for address i am looking.


LatLngCallback callback = new LatLngCallback() {

public void onFailure() {
statusLabel.setText("Address was Not Found");
}
public void onSuccess(LatLng point) {
------
------
------
}
What we are doing above is, creating an instance of LatLngCallback that will be passed as an input parameter for Geocoder class. We will have to implement onFailure and onSuccess handler methods. In our example if address is found, we will plot that location with a marker.



Geocoder geocoder= new Geocoder();
geocoder.getLatLng("dallas downtown", callback);
This is critical but simple, what we are doing above is creating an instance of Geocoder and calling getLatLng() method, which take two parameters. It takes the address you are trying to search as string and a LatLngCallback handler.
Behind the scenes at run time, google maps api will try to contact google servers to pharse latitude and longitude values of given address, if pharse was successfull it executes the onSuccess() method and if pharse has failed it executes onFailure() method.


Note that in order to use the Maps API in live, you need to apply for a Google Maps API key. But if you are running it on localhost you dont need that.


Let Talk about gmaps.gwt.xml , as you know its a GWT module configuration file. Here is how it looks

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 1.7.0//EN" "http://google-web-toolkit.googlecode.com/svn/tags/1.7.0/distro-source/core/src/gwt-module.dtd">
<module rename-to='gmaps'>
<inherits name="com.google.gwt.maps.GoogleMaps" />
<script src="http://maps.google.com/maps?gwt=1&file=api&v=2&sensor=false" />
<entry-point class='com.gwtbasics.gmaps.client.GMapsModule'/>
</module>
Place close attention at highlighted code.


<script src="http://maps.google.com/maps?gwt=1&file=api&v=2&sensor=false" />
You can see, we are not specifying any key here, as we are running this on localhost. If you run on server you need a key. You can replace ??? with key value
<script src="http://maps.google.com/maps?gwt=1&file=api&v=2&key=???" />
One Last bit of our module is the html file. I have to say, its layout looks simple and not fancy. I am just concentrating on the functionality. Here is the html file.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<style type="text/css">
h1 {
font-size: 2em;
font-weight: bold;
color: #777777;
margin: 40px 0px 70px;
text-align: center;
}
</style>
<title>SimpleMaps Module</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="gmaps/gmaps.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>

<h1>SimpleMaps</h1>
<div align=" center" id="statusLabel"></div>
<div align=" center" id="mapWidget"></div>

</body>
</html>
For this example you need to get gmaps/gmaps.nocache.js that gets created when you compile using GWT compiler.


If you are using Google Plugin for Eclipse, just right click on the project and run/debug as Web Application and you will see the result.
But if you have generated your application through webAppCreator, you can use ant build.xml to execute. Execute hosted
ant task to invoke your app in hosted mode.

I hope you were able to successfully use Google Maps in your application and enjoyed the experience of it.

Please stay tuned to my blog for more advanced implementation of Google maps Api.

Sunday, May 24, 2009

GWT Basics...

Q) Should i try GWT ?
Ans) Honest answer is, Yes its worth trying out.

Let me try to justify my answer
  • GWT helps to develop and debug AJAX(i will talk more about ajax some other day) support web applications using standard java language.
  • GWT takes a different approach on workload distribution. Traditionally, most of the heavy lifting of web application is done on server side. Google identified that some of it could be done on client side. This leaves servers to allocate more resources for business logic processing.
  • Goodle has spend lot of time and resources into it and came up with its GWT compiler that seamlessly translates your java code into javascript and HTML that most browsers understand.
  • As we code using java, first thing that comes in to mind is re usability of code. GWT is great at write once use any where. You can create a GWT Component(widgets) and use them across the application. If its generic enough you could also use across your company(i mean on any other GWT based projects in your organization) or even make it public, so that others can use.
I am sure there are enough blogs and tutorials on web, that will tell you more good bad about GWT. So lets jump in and write our first GWT application.

I personally like eclipse and been using it in all my projects. There are some great GWT plugin's available for Eclipse that will ease your development.I use
Google Plugin for Eclipse and you can get it here.
Once you have plugin succesfully installed, Create a new Web Application Project in eclipse. Go to File-> New -> Web Application Project. I am going to name it as AssetTracking.

If you dont fancy using plugin, You can manually download and install gwt on your local system from this Location. GWT ships with a command line utility called webAppCreator that automatically generates all the files you'll need in order to start a GWT project. It also generates Eclipse project files and launch config files for easy hosted mode debugging
webAppCreator -out AssetTracking com.assetTracking.AssetTracking
Once you have your project created, you can import it in to eclipse. Above command will also create a sample application which you can ignore. What we really need is the ant's build.xml that gets created, i will explain its use later.

Let me first show you the folder structure and list of files you will be needing at a minimum for creating and using a GWT Module.
AssetTracking/src/com/gwtbasics/assetTracking/AssetTracking.gwt.xml
AssetTracking/src/com/gwtbasics/assetTracking/client/AssetService.java
AssetTracking/src/com/gwtbasics/assetTracking/client/AssetServiceAsync.java
AssetTracking/src/com/gwtbasics/assetTracking/client/AssetTracking.java
AssetTracking/src/com/gwtbasics/assetTracking/server/AssetServiceImpl.java
AssetTracking/war/AssetTracking.html
AssetTracking/war/WEB-INF/web.xml

Start by creating Service Interfaces and their implementation classes.
  • Create a service interface that lists out all server side calls that are needed. Lets have one call for now, that will fetch asset name for given ID. Some thing like public String getAssetAsString(String id).
    AssetService interface will look like this.

    package com.gwtbasics.assetTracking.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("asset")
    public interface AssetService extends RemoteService {
    public String getAssetAsString(String id);
    }

  • AssetService.java is our client side stub. For server side implementation in RPC you will create AssetServiceImpl.java and it should extend RemoteServiceServlet and implements AssetService

    package com.gwtbasics.assetTracking.server;

    import com.google.gwt.user.server.rpc.RemoteServiceServlet;
    import com.gwtbasics.assetTracking.client.AssetService;

    /**
    * The server side implementation of the RPC service.
    */
    @SuppressWarnings("serial")
    public class AssetServiceImpl extends RemoteServiceServlet implements
    AssetService {

    public String getAssetAsString(String input) {
    return "Asset Name for id="+input+" is USPS Whale Shipment";
    }
    }

  • We now have client side stub as AssetService.java, Server side implementation as AssetServiceImpl.java. All we need now is a client side Async handler. This would be AssetServiceAsync.java and it would look like this.

    package com.gwtbasics.assetTracking.client;

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

    /**
    * The async counterpart of AssetServiceAsync.
    */
    public interface AssetServiceAsync {
    void getAssetAsString(String input, AsyncCallback callback);
    }

    Give a close look at the
    getAssetAsString(String input, AsyncCallback callback) method declaration and compare with getAssetAsString of AssetService.java. i am sure you will notice some difference.
Now that we have all our Service related classes, lets go ahead and use them. We will now create an EntryPoint implementation class. Entrypoint in GWT is an Interface and has an onModuleLoad() method, which we will have to implement.
package com.gwtbasics.assetTracking.client;

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 onModuleLoad().
*/
public class AssetTracking 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 Asset service.
*/
private final AssetServiceAsync greetingService = GWT
.create(AssetService.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");
// 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);
// 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("Sending id to the server:"));
dialogVPanel.add(textToServerLabel);
dialogVPanel.add(new HTML("
Server replies:"));
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() {
sendButton.setEnabled(false);
String textToServer = nameField.getText();
textToServerLabel.setText(textToServer);
serverResponseLabel.setText("");
greetingService.getAssetAsString(textToServer,
new AsyncCallback() {
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);
}
}


Next comes the AssetTracking.gwt.xml , This is a GWT module configuration file. In this you can tell where you are inheriting from and what the entry point class is.

Here are some of the Tags that are important.
  1. inherits name='com.google.gwt.user.User' --- (This tells where your current hirarchy is extending from. similar to class extension in java)
  2. entry-point class='com.gwtbasics.assettracking.client.AssetTracking' --- (This tells what is the entry point for your gwt, first class that gets invoked. Any class mentioned here should extend from com.google.gwt.core.client.EntryPoint)
<?xml version="1.0" encoding="UTF-8"?>
<DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 1.7.0//EN" "http://google-web-toolkit.googlecode.com/svn/tags/1.7.0/distro-source/core/src/gwt-module.dtd">
<module rename-to='assettracking'>
<!-- 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.gwtbasics.assetTracking.client.AssetTracking'/>
</module>

Now lets go ahead and write our html file and use above created module.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">

<style type="text/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;
}
</style>

<title>Asset Tracking Sample Project Using GWT</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="assettracking/assettracking.nocache.js"></script>
</head>

<body>

<iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe>

<h1>Asset Tracking Sample Project Using GWT</h1>

<table align="center">
<tr>
<td colspan="2" style="font-weight:bold;">Please enter your name:</td>
</tr>
<tr>
<td id="nameFieldContainer">
<td id="sendButtonContainer">
</tr>
</table>
</body>
</html>

Lets write our last bit of code. Its the web.xml file that has our AssetService and appropriate servlet mappings.
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<!-- Servlets -->
<servlet>
<servlet-name>assetServlet
<servlet-class>com.gwtbasics.assetTracking.server.AssetServiceImpl
</servlet>

<servlet-mapping>
<servlet-name>assetServlet
<url-pattern>/assettracking/asset
</servlet-mapping>

<!-- Default page to serve -->
<welcome-file-list>
<welcome-file>AssetTracking.html
</welcome-file-list>
</web-app>
Here we created full set of files for our first GWT application.

So how do we compile and run this thing? Easy i say...

If you are using
Google Plugin for Eclipse, just right click on the project and run/debug as Web Application and you will see the result.
But if you have generated your application through webAppCreator, you can use ant build.xml to execute. You need to execute hosted
ant task to invoke your app in hosted mode.

I hope you were able to successfully create your first web app using GWT and enjoied it.

Please stay tuned to my blog for more advanced topics on GWT.