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.

No comments:

Post a Comment