lab5 google maps

Upload: emicono

Post on 04-Jun-2018

229 views

Category:

Documents


0 download

TRANSCRIPT

  • 8/13/2019 Lab5 Google Maps

    1/24

    Page 1 of 24

    Lab 5Google Maps

    In this lab you will use the results of Lab 3 to display the location of the cellular phone in

    a Google Map in real-time. You will use the part of Lab 3 that obtains GPS fixes every

    10 seconds and sends them using UDP to the database on a server.

    Objective

    The objective to this lab is to:

    1. Create a Google Web Toolkit Project2. Learn how to use Remote Procedure Calls (RPC) in GWT3. Learn how to use the Google Maps to create a simple mapping application

    Experiment 1 Writing the server-side code

    In this part you will create the required NetBeans project to develop a Google Map

    application.

    To get started with the NetBeans project, do the following steps:

    1. Run NetBeans2. Create a new project (File -> New Project)3. Choose Java Web -> Web Application and Click Next4. Write in your project name, e.g., Lab 5 and select the appropriate path where to

    store it

    5. Select the server where you will be deploying your application and the ContextPath for your app. Click Next and Finish6. Your Lab 5 project appears in the upper left window7. Right Click in projects name and in the menu click Properties8. In the categories list, click Libraries9. Click Add JAR/Folder button, go to your gwt installation folder, select the gwt-

    servlet.jar and click open

  • 8/13/2019 Lab5 Google Maps

    2/24

    Page 2 of 24

    10.Click Add JAR/Folder button, go to your Postgres installation folder, look for thejdbc folder and select the posgis_1.3.3.jar. Click Open and then Click Ok.

    11.Right Click on Source Packages, and in the menu that appears, click New->Package.

    12.Write the package name as cse.usf.edu.lab5.client.services and click finish

    13.Repeat steps 11 and 12, with the new package name beingcse.usf.edu.lab5.client.entities

    In this exercise you will write the server-side code for the Google Map application. This

    code will create the server-side methods that will invoke the database to obtain the lastlocation stored in the database of the active users.

    1. Right click in the package cse.usf.edu.lab5.client.entities and in the menu clickNew->Java class

    2. Write down the name of the class as TrackingUpdate. Click finish3. Select all the code that appears in the TrackingUpdate.java screen and delete it

    4. Copy and paste the following code in that area and save it (File->Save)

    Listing 1- TrackingUpdate.java

    package cse.usf.edu.lab5.client.entities;

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

    // A GWT serializable class used to encapsulate the information about activesessions

    public class TrackingUpdate implements IsSerializable{private double latitude;private double longitude;private int sessionid;private String username;

    public TrackingUpdates(){

    }public int getsessionId(){

    return sessionid;}public String getUsername(){

    return username;}public double getLatitude(){

    return latitude;}public double getLongitude(){

  • 8/13/2019 Lab5 Google Maps

    3/24

    Page 3 of 24

    return longitude;}public void setSessionid(int sessionid){

    this.sessionid = sessionid;}public void setUsername(String usr){

    this.username = usr;}public void setLatitude(double lat){

    this.latitude = lat;}public void setLongitude(double lng){

    this.longitude = lng;}

    }

    This code is a simple wrapper of the session information. There are two important aspects

    to show of this code:

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

    This line is importing an interface called isSerializable from the Google Web Toolkitlibrary. A serializable object is an object that can be transmitted and received by the

    client-side and server-side applications in the same form without the programmers

    intervention in coding and decoding it from its state to a byte stream and vice versa.

    public class TrackingUpdate implements IsSerializable

    This line is stating that the TrackingUpdate class is implementing the IsSerializableinterface.

    Now, we need to create the service interface and the implementation of the interface. In

    order to do this, follow the next steps:

    1. Right click in the package cse.usf.edu.lab5.client.services and in the menu clickNew->Java interface

    2. Write down the name of the interface as TrackingServiceManager. Click finish3. Select all the code that appears in the TrackingServiceManager.java screen and

    delete it

    4. Copy and paste the following code in that area and save it (File->Save)

    Listing 2- TrackingServiceManager.java

    package cse.usf.edu.lab5.client.services;

    import com.google.gwt.user.client.rpc.RemoteService;import cse.usf.edu.lab5.client.entities.TrackingUpdate;

  • 8/13/2019 Lab5 Google Maps

    4/24

    Page 4 of 24

    // An interface that exposes a method that returns the session updates.

    public interface TrackingServiceManager extends RemoteService{public TrackingUpdate[] getTrackingUpdates();}

    There are two important aspects to show of this code. The line,

    import com.google.gwt.user.client.rpc.RemoteService

    is importing an interface called RemoteService from the Google Web Toolkit library.This interface does not provide any methods, but its functionality is to state that the

    service interface that you wrote is going to be utilized by the Google Web Toolkit as a

    service provider. This is stated in the line

    public interface TrackingServiceManager extends RemoteService

    The next step is to write the service implementation. To do this, follow the nextinstructions:

    1. Right click in the package cse.usf.edu.lab5.client.services and in the menu clickNew->Java class

    2. Write down the name of the interface as TrackingServiceManagerImpl. Clickfinish

    3. Select all the code that appears in the TrackingServiceManagerImpl.java screenand delete it

    4. Copy and paste the following code in that area and save it (File->Save)

    Listing 3- TrackingServiceManagerImpl.java

    package cse.usf.edu.lab5.client.services;

    import com.google.gwt.user.server.rpc.RemoteServiceServlet;

    import cse.usf.edu.lab5.client.entities.TrackingUpdate;

    import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import java.util.Iterator;import java.util.LinkedList;import java.util.List;import java.util.logging.Level;import java.util.logging.Logger;

  • 8/13/2019 Lab5 Google Maps

    5/24

    Page 5 of 24

    import javax.naming.NamingException;import org.postgis.Point;

    // Provides server side implementation of the TrackingServiceManager interface

    public class TrackingServiceManagerImpl extends RemoteServiceServlet

    implements TrackingServiceManager{

    public TrackingUpdate[] getTrackingUpdates(){

    Connection theConnection = null;try{

    javax.naming.InitialContext ic = new javax.naming.InitialContext();javax.sql.DataSource dataSource =

    (javax.sql.DataSource)ic.lookup("jdbc/lbsclass");theConnection = dataSource.getConnection();

    PreparedStatement queryStatement =theConnection.prepareStatement("select fieldsession.sessionid as sesid,fielduser.username as uname, ST_AsText(tracking.position) as pos "+

    "from fieldsession,tracking,fielduser, (select max(idtracking) as idtrack "+ "from fieldsession, tracking"+ "where fieldsession.datestop is NULL and fieldsession.sessionid =tracking.sessionid "+"group by fieldsession.sessionid) as s2 "+"wherefieldsession.datestop is NULL and "+"fieldsession.sessionid = tracking.sessionidand "+ "tracking.idtracking = s2.idtrack and "+"fieldsession.iduser =fielduser.iduser");

    ResultSet rs = queryStatement.executeQuery();

    List returnList = new LinkedList();while(rs.next()){

    TrackingUpdate newUpdate = new TrackingUpdate();

    newUpdate.setSessionid(rs.getInt("sesid"));newUpdate.setUsername(rs.getString("uname"));

    Point theNewPoint = new Point(rs.getString("pos"));

    newUpdate.setLongitude(theNewPoint.getX());

    newUpdate.setLatitude(theNewPoint.getY());

    returnList.add(newUpdate);}theConnection.close();

    if(!returnList.isEmpty()){

  • 8/13/2019 Lab5 Google Maps

    6/24

    Page 6 of 24

    TrackingUpdate theReturnVector[] = newTrackingUpdate[returnList.size()];

    int i = 0;for (Iterator it = returnList.iterator(); it.hasNext();){

    TrackingUpdate theUpdate = (TrackingUpdate) it.next();

    theReturnVector[i] = theUpdate;i++;

    }return theReturnVector;

    }return null;

    }catch (NamingException ex){

    Logger.getLogger(TrackingServiceManagerImpl.class.getName()).log(Level.SEVERE, null, ex);

    try {

    theConnection.close();} catch (SQLException ex1) {

    Logger.getLogger(TrackingServiceManagerImpl.class.getName()).log(Level.SEVERE, null, ex1);

    }}catch (SQLException ex){

    Logger.getLogger(TrackingServiceManagerImpl.class.getName()).log(Level.SEVERE, null, ex);

    }

    return null;}

    }

    In order to understand the code, read the following explanation carefully.

    There are many imports in this file. The first import that is written in the code is

    import com.google.gwt.user.server.rpc.RemoteServiceServlet;

    This import is required because it provides the GWT service functionality. GWT services

    are pieces of code that execute over servlets. In Java, servlets are classes that listen for

    HTTP requests in a URL and execute code in the server when a client invokes such URL.The import that comes after this,

    import cse.usf.edu.lab5.client.entities.TrackingUpdate;

  • 8/13/2019 Lab5 Google Maps

    7/24

    Page 7 of 24

    is making available the class which objects are going to be returned to the client upon the

    service invocation.

    The next set of imports

    import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import java.util.Iterator;import java.util.LinkedList;import java.util.List;

    correspond to the SQL libraries in Java and the list and linked list classes available in the

    standard J2SE API.

    The following set of imports

    import java.util.logging.Level;import java.util.logging.Logger;import javax.naming.NamingException;

    correspond to the management of the exceptions (errors) that can be raised when the

    query is performed in the database.

    Finally the last importimport org.postgis.Point;

    provides a wrapper of the point object stored in the database. We will use these objects to

    translate the coordinates obtained from the query to latitude and longitude values.

    The basic idea of this code is to provide an implementation of the service interface for theTrackingManagerService. In order to do this, the TrackingManagerService.java class

    must provide an implementation of such interface. In Java, an implementation of an

    interface means to write code in a method whose name and parameters and return value

    correspond to the ones that are declared in the interface. Look that in the declaration ofthe class

    public class TrackingServiceManagerImpl extends RemoteServiceServletimplements TrackingServiceManager{

    it states that the class is implementing the TrackingServiceManager interface. Remember

    from Listing 2 that the interface is only declaring one procedure

    public TrackingUpdate[] getTrackingUpdates();

    This method is therefore the one that is implemented in the TrackingServiceManagerImplclass. In general, the implementation will query the database to get the location of those

  • 8/13/2019 Lab5 Google Maps

    8/24

    Page 8 of 24

    sessions that are active in the system. Those sessions correspond to the sessions in the

    database whose date end is null.

    The code is basically divided into three sections:

    1. Connecting to the database and execution of the query2. Retrieving of the results of the query3. Returning an array of TrackingUpdate objects with the information about

    sessions.

    1. Connecting to the database and execution of the query

    For connecting to the database, the code uses a connection pool resource that isprovided by the server where the application is deployed. The code that perform this

    is

    Connection theConnection = null;

    javax.naming.InitialContext ic = new javax.naming.InitialContext();javax.sql.DataSource dataSource =javax.sql.DataSource)ic.lookup("jdbc/lbsclass");

    theConnection = dataSource.getConnection();

    The connection in the code above is obtained by using the jdbc/lbsclass resource from

    the database. This code looks for the resource (InitialContect ic = new ), get thedata source and after this, it gets the connection. If the resource is not found, the code

    will throw a NamingException.

    Now that if the connection is obtained, the code will invoke the database with a query

    wrapped in a PreparedStatement object called queryStatement

    PreparedStatement queryStatement = theConnection.prepareStatement("selectfieldsession.sessionid as sesid, fielduser.username as uname,ST_AsText(tracking.position) as pos "+

    "from fieldsession, tracking,fielduser, (select max(idtracking) as idtrack "+"from fieldsession, tracking "+"where fieldsession.datestop is NULLand fieldsession.sessionid =

    tracking.sessionid "+group by fieldsession.sessionid) as s2 "+

    "where fieldsession.datestop is NULL and "+"fieldsession.sessionid = tracking.sessionid and "+"tracking.idtracking = s2.idtrack and "+"fieldsession.iduser = fielduser.iduser");

    ResultSet rs = queryStatement.executeQuery();

  • 8/13/2019 Lab5 Google Maps

    9/24

    Page 9 of 24

    This code is obtaining the last received location per active session in the system. In

    order to do this, the SQL query uses a subquery in the from

    (select max(idtracking) as idtrack from fieldsession, trackingwhere fieldsession.datestop is NULL and fieldsession.sessionid = tracking.sessionidgroup by fieldsession.sessionid) as s2

    which provides the id of the last valid received location of any active session.Looking at this subquery, an active session is a session whose datestop is null. As this

    subquery is performed in the from part of the query, the results are seen by the

    database engine as a table. These results are then cross producted with the otherstables (fieldsession, and tracking) in order to obtain the information we want, which

    is the sessionid, the username, and the location of each active session. The statement

    ResultSet rs = queryStatement.executeQuery();

    is the one that performs the query to the database.

    2. Retrieving of the results of the query

    As there is no way to know beforehand the number of records in the ResultSet tosafely allocate the size of the returning TrackingUpdate array, we will use a list of

    TrackingUpdate objects as intermediate storage for obtaining the records from the

    ResultSet and know the size of the returning array. The code that provides this

    functionality is

    List returnList = new LinkedList();

    while(rs.next()){

    TrackingUpdate newUpdate = new TrackingUpdate();

    newUpdate.setSessionid(rs.getInt("sesid"));newUpdate.setUsername(rs.getString("uname"));

    Point theNewPoint = new Point(rs.getString("pos"));

    newUpdate.setLongitude(theNewPoint.getX());newUpdate.setLatitude(theNewPoint.getY());

    returnList.add(newUpdate);}theConnection.close();

    This code iterates over the ResultSet, creating a TrackingUpdate object per active

    session record in the database and adding each object to a list (returnList). From this

    code observe the lines

  • 8/13/2019 Lab5 Google Maps

    10/24

    Page 10 of 24

    Point theNewPoint = new Point(rs.getString("pos"));newUpdate.setLongitude(theNewPoint.getX());newUpdate.setLatitude(theNewPoint.getY());

    As the location is obtained as a text string from the query, the org.postgis.Point objectis providing the parsing from string to double values for the latitude and longitude.

    Once all the records have been placed in the list, we can know the size of the array.

    3. Returning an array of TrackingUpdate objects with the information about sessions

    The last part of this code is the one that returns the array. The code which is shown

    below, builds an array of TrackingUpdates using the size of the list for its own size.

    After this, it basically iterates over the list, and copies the contents of the list to the

    array. If the list is empty, the procedure will return null.

    if(!returnList.isEmpty()){

    TrackingUpdate theReturnVector[] = newTrackingUpdate[returnList.size()];

    int i = 0;for (Iterator it = returnList.iterator(); it.hasNext();){

    TrackingUpdate theUpdate = (TrackingUpdate) it.next();theReturnVector[i] = theUpdate;i++;

    }return theReturnVector;

    }return null;

    In order to test the database, use the following username and password to connect to the

    lbsclass_lab5 database and set up your connection pool and jdbc resource in the Sun JavaApplication Server.

    Username: lbsclass

    Password: lab5

    Set up a connection in the PgAdmin so you can run the select query statement from

    there. We have populated the database with some information. The result of the queryshould be:

    424;phoneuser4;POINT(-82.4563676118851

    27.9414403438568)813;taclan0;POINT(-82.41131528.0601866666667)848;ajperez4;POINT(-82.41472166666667 28.0598483333333)

  • 8/13/2019 Lab5 Google Maps

    11/24

    Page 11 of 24

    This corresponds to the locations and active sessions in the database that are used to show

    the locations in the map.

    The lbsclass_lab5 database is the one that you should use for your lab.

    Now that we have the implementation developed, the next step is to register theimplementation with the Web application deployment descriptor. To do this, follow the

    next steps:

    1. Go to the Project panel, click on the + sign of the label Configuration and doubleclick over the web.xml file

    2. A page that contains the configuration of the application appears on the right side.Click on the Servlets button and click the Add Servlet Element button

    3. In the window, write GwtDeviceManager in the Name textfield. In the Servletclass click on the Browse button and look for theTrackingServiceManagerImpl.java class. In URL Pattern(s) write

    /services/TrackingManager. Click OK and click the File->Save

    4. When deployed, the URL of the TrackingManager will behttp://ip_machine:port/lab5/services/TrackingManager. This URL will be used by

    the client to invoke the service.

    At this point, the server side code can be deployed. To do this, go to the Projects panel,

    right click on the project, and choose the Clean and Build option. After the building

    process is completed, go again to the Projects panel, right click on the project, and choosethe Deploy option.

    Now, we are ready to create the Eclipse GWT project.

    Experiment 2 Creating a GWT project in Eclipse and configuring it to use GoogleMaps

    In this part you will create the Eclipse GWT project to develop a Google Map

    application.

    To get started, do the following steps:

    1. Go to the Windows Command line. (Start button -> Run, in the Open text boxwrite cmd.exe and click OK

    2. Change folder to the folder you have placed the Google Web Toolkit3. Write the following commands

    projectCreator -eclipse Lab5 -out Lab5

  • 8/13/2019 Lab5 Google Maps

    12/24

    Page 12 of 24

    and then

    applicationCreator -eclipse Lab5 -out Lab5 -overwrite cse.usf.edu.lab5.client.Lab5

    4. Open Eclipse, and select your workspace5. Go to menu File->Import, under General select Existing projects into Workspaceand click Next

    6. Select the root directory which in our case is the folder where the GWT wasinstalled. Click OK

    7. Now check the option Copy projects into workspace and click Finish8. Run the project, to do this right click on the project name in the Package Explorer

    (upper right side) Run As -> Run Configurations

    9. On the left side of the window, click Java Application and select Lab5. Click Run10.To close the application, close the Google Web Toolkit Development Shell

    Now we have a basic GWT project on which we will develop the visualization of the

    sessions.11.Create a Google Maps key for thehttp://localhost:8888/by signing with Google

    in the following URL http://code.google.com/apis/maps/signup.html

    12.Add the Google Maps library to the project. To do this right click in the projectname in the Package Explorer, then in the menu click Properties. Click in Java

    Build Path and in the right panel click in Libraries. Now click Add External JAR,search and select the gwt-maps.jar file. Click Open and OK.

    13.Use the package explorer to find the Lab5.gwt.xml file. This file should be in thesrc->cse.usf.edu.lab5 path. Right click in the file and then in the menu click OpenWith->Text Editor.

    Under the line write the following:

    Under the line write the following line

    Replace the your_key with the key obtained in step 11 and save the changes to thefile.

    Every application developed with GWT has a .gwt.xml file. This file can be seen as theapplication descriptor. It contains information that the GWT shell and compiler utilize to

    link external JavaScript libraries and start the application.

    http://localhost:8888/http://localhost:8888/http://localhost:8888/http://code.google.com/apis/maps/signup.htmlhttp://code.google.com/apis/maps/signup.htmlhttp://code.google.com/apis/maps/signup.htmlhttp://localhost:8888/
  • 8/13/2019 Lab5 Google Maps

    13/24

    Page 13 of 24

    Experiment 3 Creating a visual interface that uses Google Maps to show the activesessions in the system

    1. Create two packages in your Eclipse project named exactly the same as the ones

    of steps 12 and 13 of Experiment 1. To do this, right click in the projects name inthe Package Explorer, and in the menu click New->Package

    2. Create a class as shown in Listing 1 under the packagecse.usf.edu.lab5.client.entities . Copy the contents of Listing 1 to this class

    3. Create an interface as shown in Listing 2 under the package cse.usf.edu.lab5.client.services. Copy the contents of Listing 2 to thisinterface

    4. Under the package cse.usf.edu.lab5.client.services create an interface calledTrackingServiceManagerAsync

    5. Select all the code that appears in the TrackingServiceManager.java screen anddelete it

    6. Copy and paste the following code in that area and save it (File->Save)

    Listing 4- TrackingServiceManagerAsync.java

    package cse.usf.edu.lab5.client.services;

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

    import cse.usf.edu.lab5.client.entities.TrackingUpdate;

    public interface TrackingServiceManagerAsync {public void getTrackingUpdates(AsyncCallback callback);

    }

    7. Create a new class called TrackingWindow under the cse.usf.edu.lab5.clientpackage. Erase all the code that appears in the TrackingWindow.java and replace

    it by the code shown in Listing 5

    Listing 5- TrackingServiceManager.java

    package cse.usf.edu.lab5.client;

    import com.google.gwt.core.client.GWT;

    import com.google.gwt.user.client.*;import com.google.gwt.user.client.ui.*;import com.google.gwt.user.client.rpc.AsyncCallback;import com.google.gwt.user.client.rpc.ServiceDefTarget;

  • 8/13/2019 Lab5 Google Maps

    14/24

    Page 14 of 24

    import com.google.gwt.maps.client.InfoWindowContent;import com.google.gwt.maps.client.MapWidget;import com.google.gwt.maps.client.control.LargeMapControl;import com.google.gwt.maps.client.control.MapTypeControl;import com.google.gwt.maps.client.event.MarkerClickHandler;

    import com.google.gwt.maps.client.geom.LatLng;import com.google.gwt.maps.client.overlay.Marker;

    import cse.usf.edu.lab5.client.entities.TrackingUpdate;import cse.usf.edu.lab5.client.services.TrackingServiceManager;import cse.usf.edu.lab5.client.services.TrackingServiceManagerAsync;

    public class TrackingWindow extends Composite {

    private AbsolutePanel backgroundPanel = null;private MapWidget theMapWidget = null;private Timer trackingTimer = null;

    public TrackingWindow() {super();initializeComponents();setLayout();setProperties();

    }

    protected void initializeComponents(){backgroundPanel = new AbsolutePanel();theMapWidget = new MapWidget();backgroundPanel.add(theMapWidget, 1,1);

    updateActiveSessions();trackingTimer = new Timer(){

    public void run(){

    updateActiveSessions();}

    };trackingTimer.scheduleRepeating(10000);

    }

    protected void setLayout(){initWidget(backgroundPanel);

    }

    protected void setProperties(){setHeight("600");

  • 8/13/2019 Lab5 Google Maps

    15/24

    Page 15 of 24

    setWidth("800");

    backgroundPanel.setHeight("600");backgroundPanel.setWidth("800");

    theMapWidget.setHeight("600");

    theMapWidget.setWidth("800");theMapWidget.addControl(new LargeMapControl());theMapWidget.addControl(new MapTypeControl());

    }

    public void updateActiveSessions(){

    }}

    8. Replace the updateActiveSessions() method of the above code with the codeshown in Listing 6. Replace the String serviceURL = .... line with the followingline:

    String serviceURL = http://ip_machine:port/lab5/services/TrackingManager;

    where ip_machine:port corresponds to the ip and HTTP port number where your

    server side code is deployed.

    9. Open the Lab5.java class which can be found in the cse.usf.edu.lab5.clientpackage. Modify the onModuleLoad() as shown in Listing 7. Save the code.

    Listing 6- The updateActiveSessions method

    public void updateActiveSessions(){

    TrackingServiceManagerAsync theTrackingManager =(TrackingServiceManagerAsync) GWT.create(TrackingServiceManager.class);

    ServiceDefTarget endpoint = (ServiceDefTarget) theTrackingManager;String remoteServiceURL =

    "http://localhost:8080/LbsBook/services/TrackingManager";endpoint.setServiceEntryPoint(remoteServiceURL);

    AsyncCallback callback = new AsyncCallback(){

    public void onSuccess(Object result){

    TrackingUpdate theUpdates[] = (TrackingUpdate[]) result;if(theUpdates != null){

    theMapWidget.clearOverlays();

  • 8/13/2019 Lab5 Google Maps

    16/24

    Page 16 of 24

    for(int i = 0; i < theUpdates.length; i++){

    final LatLng coordinates =LatLng.newInstance(theUpdates[i].getLatitude(), theUpdates[i].getLongitude());

    final String theString = "Username:"+theUpdates[i].getUsername()+"
    Session id:"+theUpdates[i].getsessionId();

    Marker theNewMarker = new Marker(coordinates);

    MarkerClickHandler theHandler = new MarkerClickHandler(){public void onClick(MarkerClickEvent event) {

    theMapWidget.getInfoWindow().open(coordinates, newInfoWindowContent(theString));

    }

    };

    theNewMarker.addMarkerClickHandler(theHandler);theMapWidget.addOverlay(theNewMarker);

    }}

    }

    public void onFailure(Throwable caught){

    Window.alert("An Internal Error has ocurred: " +caught.getMessage());

    trackingTimer.cancel();}

    };

    theTrackingManager.getTrackingUpdates(callback);}

    Listing 7- The onModuleLoad method in Lab5.java class

    public void onModuleLoad(){VerticalPanel vPanel = new VerticalPanel();vPanel.setWidth("100%");vPanel.setHorizontalAlignment(VerticalPanel.ALIGN_CENTER);

    RootPanel.get().add(vPanel);TrackingWindow theWindow = new TrackingWindow();final DialogBox dialogBox = new DialogBox();

  • 8/13/2019 Lab5 Google Maps

    17/24

    Page 17 of 24

    dialogBox.setText("Map Example");dialogBox.setAnimationEnabled(true);dialogBox.add(theWindow);dialogBox.center();dialogBox.show();

    }

    In order to understand the code, read the following explanation carefully. First take alook at the TrackingWindow.java file.

    There are many imports in this file. The first import that is written in the code isimport com.google.gwt.core.client.GWT;

    This line is importing core functionalities from the framework, utilized for creating/loadingclasses in runtime. This is used in the code for creating the proxy that will perform the RPC(Remote Procedure Call).

    The next set of imports are needed for the user interface

    import com.google.gwt.user.client.*;import com.google.gwt.user.client.ui.*;

    The following imports are needed for the classes that perform the remote procedure call

    to the server (to get the session location updates).

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

    ;

    Now this set of imports is needed to utilize the Google Maps classes. The first import inthe set is the MapWidget. This class represents the Google Maps. The second and third

    (LargeMapControl and MapTypeControl) provides the map with the controllers to scroll

    the map and zoom to it and choose the map type (satellite, physical, etc...). The next two

    (MarkerClickHandler and InfoWindowContent) are needed as we will display the sessioninformation in a box when a balloon that represents the location of a session is clicked.

    Finally the last two imports of this set (the LatLng and the Marker) are used for themarkers that are shown in the map and the location of such markers.

    import com.google.gwt.maps.client.MapWidget;import com.google.gwt.maps.client.control.LargeMapControl;import com.google.gwt.maps.client.control.MapTypeControl;import com.google.gwt.maps.client.event.MarkerClickHandler;import com.google.gwt.maps.client.InfoWindowContent;import com.google.gwt.maps.client.geom.LatLng;import com.google.gwt.maps.client.overlay.Marker;

  • 8/13/2019 Lab5 Google Maps

    18/24

    Page 18 of 24

    Finally, the last set of imports for this class are

    import cse.usf.edu.lab5.client.entities.TrackingUpdate;import cse.usf.edu.lab5.client.services.TrackingServiceManager;import cse.usf.edu.lab5.client.services.TrackingServiceManagerAsync;

    These correspond to the class that abstracts the session information (TrackingUpdate) and

    the remote service interfaces.

    The main idea with this class is to provide a user interface component that every ten

    seconds retrieves updates about the sessions in the system and show such information in amap. In GWT those own UI components can be developed by extending the Composite

    class. The Composite class in GWT is provided to wrap user components in a single

    window (similar to the Jframe class in J2SE). Look that we do this on this line:

    public class TrackingWindow extends Composite

    The TrackingWindow class has three private variables, these are:

    private AbsolutePanel backgroundPanel = null;private MapWidget theMapWidget = null;private Timer trackingTimer = null;

    The first variable (backgroundPanel) is utilized as the base panel where the components of the

    TrackingWindow will be added. The second (theMapWidget) is the instance of the Google Mapswhere the locations will be shown. Finally, the third variable (trackingTimer) provides us with thefunctionality to invoke the server every ten seconds.

    The TrackingWindow class is made of 5 methods:

    public TrackingWindow(): Constructor of the class. This method invokes theinitializeComponents, setLayout, and setProperties methods.

    protected void initializeComponents(): Initializes the three variables. This method is alsoutilized to setup the timer to invoke the update of the session information every 10 seconds.

    protected void setLayout(): Initializes the background panel.

    protected void setProperties(): Set the sizes for the background panel and for the MapWidget.

    public void updateActiveSessions(): Invokes the remote server procedure to update the sessioninformation. This method is the one that the timer invokes every 10 seconds.

    From these methods, we will explain the updateActiveSessions and the initializeComponents

    method as these are the two most important methods of this class.

  • 8/13/2019 Lab5 Google Maps

    19/24

    Page 19 of 24

    As it has been stated before, the updateActiveSessions performs the invocation of the remoteprocedure in the server. In order to do this, the method performs the following steps:

    Proxy creation:The proxy is created by the factory method GWT.create() in the line

    TrackingServiceManagerAsync theTrackingManager = (TrackingServiceManagerAsync)GWT.create(TrackingServiceManager.class);

    using the service interface and returning an object that implements the asynchronousservice interface. The proxy transmits the objects using HTTP, hiding the details from the

    programmers.

    Remote service location set up: A remote service location is set up in the lines

    ServiceDefTarget endpoint = (ServiceDefTarget) theTrackingManager;String remoteServiceURL = "http://localhost:8080/LbsBook/services/TrackingManager";

    endpoint.setServiceEntryPoint(remoteServiceURL);

    where the URL of the Web object that implements the RPC service is located.

    Manager of the response set up: A response manager is set up between the linesAsyncCallback callback = new AsyncCallback(){

    public void onSuccess(Object result){

    ..}

    public void onFailure(Throwable caught){

    ...}

    };

    where the callback object is created. AsyncCallback is an interface that implements two

    methods. The first, which is onSuccess(), is executed when the RPC is completed with

    success. The other, onFailure(), is executed if there is a communication failure with theserver. Here we are creating an anonymous class that implements the AsyncCallback

    interface. In our code, the onSuccess method will be adding the session information to the

    Google Map. The onFailure() method will show a dialog box showing that somethingwent wrong when performing the invocation.

    Objects preparation and RPC service invocation: This is done on the linetheTrackingManager.getTrackingUpdates(callback);

    which is the line that actually performs the RPC call. In our example, there are no

    parameters for the invocation of the RPC. A question that you might be asking now is

  • 8/13/2019 Lab5 Google Maps

    20/24

    Page 20 of 24

    why the AsyncCallback object is used to manage the response of the communication. The

    answer for this is as programs in JavaScript are single threaded, if there is a blocking call

    in the code, your JavaScript application freezes until the code returns. In this perspective,when you do asynchronous calls, you are avoiding the blocking of RPC calls, and

    therefore managing the invocation as events: one event that executes when the invocation

    was performed successfully, the other when it is not successful.

    Now take a look on the onSuccess of the AsyncCallback object

    public void onSuccess(Object result){

    TrackingUpdate theUpdates[] = (TrackingUpdate[]) result;if(theUpdates != null){

    theMapWidget.clearOverlays();

    for(int i = 0; i < theUpdates.length; i++){

    final LatLng coordinates =LatLng.newInstance(theUpdates[i].getLatitude(), theUpdates[i].getLongitude());

    final String theString = "Username:"+theUpdates[i].getUsername()+"
    Session id:"+theUpdates[i].getsessionId();

    Marker theNewMarker = new Marker(coordinates);

    MarkerClickHandler theHandler = new MarkerClickHandler(){public void onClick(MarkerClickEvent event) {

    theMapWidget.getInfoWindow().open(coordinates, newInfoWindowContent(theString));

    }};

    theNewMarker.addMarkerClickHandler(theHandler);theMapWidget.addOverlay(theNewMarker);

    }}

    }

    The first line TrackingUpdate theUpdates[] = (TrackingUpdate[]) result;is performing a

    casting on result parameter of the onSuccess call. In Java, casting means theinterpretation of an object as another one. To do this, in runtime the system checks the

    types for both the object you are casting and the variable that you cast to. If the types do

    not correspond, then it throws a runtime exception. In this line, we are casting the ObjectResult to a vector of TrackingUpdate objects.

  • 8/13/2019 Lab5 Google Maps

    21/24

    Page 21 of 24

    Now the following lines are adding a balloon in the MapWidget object per active session

    in the system.

    theMapWidget.clearOverlays();

    for(int i = 0; i < theUpdates.length; i++){

    final String theString = "Username:"+theUpdates[i].getUsername()+"
    Session id:"+theUpdates[i].getsessionId();

    Marker theNewMarker = new Marker(coordinates);

    MarkerClickHandler theHandler = new MarkerClickHandler(){public void onClick(MarkerClickEvent event) {

    theMapWidget.getInfoWindow().open(coordinates, newInfoWindowContent(theString));

    }};

    theNewMarker.addMarkerClickHandler(theHandler);theMapWidget.addOverlay(theNewMarker);

    }

    The first line theMapWidget.clearOverlays();

    is cleaning all the overlays in the map. After this, the code iterates over the array of

    TrackingUpdates and for every session it performs the following steps:

    Creation of a Map coordinates: This is performed in the line final LatLngcoordinates = LatLng.newInstance(theUpdates[i].getLatitude(),theUpdates[i].getLongitude());

    Creation of a marker based on the coordinates: Marker theNewMarker = newMarker(coordinates);

    Creation a click handler for the marker: Upon the click the marker, this code willdisplay a window with information about the sessionMarkerClickHandler theHandler = new MarkerClickHandler(){

    public void onClick(MarkerClickEvent event) {theMapWidget.getInfoWindow().open(coordinates, new

    InfoWindowContent(theString));}

    };

    theNewMarker.addMarkerClickHandler(theHandler);

  • 8/13/2019 Lab5 Google Maps

    22/24

    Page 22 of 24

    Adding the overlay to the map. This is performed in the linetheMapWidget.addOverlay(theNewMarker); which finally adds the marker to the

    map.

    Now go to the initalizeComponents() method of the TrackingWindow class. The

    important part of this code is the one that uses a timer to invoke the code that updates thesession information

    trackingTimer = new Timer(){

    public void run(){

    updateActiveSessions();}

    };trackingTimer.scheduleRepeating(10000);

    All code that is within the run() method will be executed every certain amount of time, inthis case, such time is setup to be 10 seconds. This is a way to emulate threads in GWT,

    however there is no thread concept in GWT, as all the applications in JavaScript are

    single threaded.

    The final explanation of this lab guide is how to initialize (entry point) a GWT

    application. Go to the Lab5.java class. You should have the code shown in Listing 8.

    Listing 8- The Lab5.java class

    package cse.usf.edu.lab5.client;

    import com.google.gwt.core.client.EntryPoint;import com.google.gwt.user.client.ui.Button;import com.google.gwt.user.client.ui.ClickListener;import com.google.gwt.user.client.ui.DialogBox;import com.google.gwt.user.client.ui.Image;import com.google.gwt.user.client.ui.RootPanel;

    import com.google.gwt.user.client.ui.VerticalPanel;import com.google.gwt.user.client.ui.Widget;

    /*** Entry point classes define onModuleLoad().*/

    public class Lab5 implements EntryPoint {

  • 8/13/2019 Lab5 Google Maps

    23/24

    Page 23 of 24

    /*** This is the entry point method.*/

    public void onModuleLoad(){

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

    RootPanel.get().add(vPanel);TrackingWindow theWindow = new TrackingWindow();final DialogBox dialogBox = new DialogBox();dialogBox.setText("Map Example");dialogBox.setAnimationEnabled(true);dialogBox.add(theWindow);dialogBox.center();dialogBox.show();

    }}

    In GWT an entry point of a GWT application is defined as a class that implements the

    EntryPoint interface. This interface declares the onModuleLoad() method that will be

    utilized as the first code that the application will execute when initialized. In this case,this code is declaring a panel where a DialogBox is added to it, and in the dialog box we

    are adding an instance of the TrackingWindow application.

    The entry point of the application is referenced in the Lab5.gwt.xml file. Look for this

    file on your project tree and you will find a line that says:

    This line is configuring you application to declare what will be the entry point, in this

    case, this is the cse.usf.edu.lab5.client.Lab5 class.

    Now that the client and server codes have been developed, it is time to compile the

    application with GWT and deploy it along with the Web Project. The following steps

    indicate how to accomplish this:

    1. Compile the Eclipse project with GWT: Run the Eclipse project and click on theCompile/Browse button2. Copy the compiled files to the Web project application: Using the Windows

    Explorer, go to the Eclipse's GWT project location and copy the folder www tothe Web folder of the NetBeans project

    3. Build and Deploy: Using NetBeans, build and deploy the Web project

  • 8/13/2019 Lab5 Google Maps

    24/24

    Page 24 of 24

    After the Web application has been deployed, it can be executed from a Web browser. In

    our case the URL to use would be http://ip_machine:port/lab5/services/TrackingManager;

    which consists of the path where the application resides in the server with IP addressip_machine:port.

    Experiment 5 Modify the TrackingWindow in such way that when the user clicks onthe map, it not only shows the marker but also shows a table with the distance in meters

    from the coordinate that corresponds to the click to each of the active sessions. You mustshow in a text field the location of the click (in lat, long format) and in the table the user,

    the location (in lat, long format), and the distance. Hint:use the FlexTable component

    for the table and look in the gwt-maps javadocs for the click map listeners for the

    MapWidget.

    Report

    Turn in your software and a written report including:

    1. Name of group members2. Date of the projects submission3. Names of all project folders submitted4. A brief set of instructions for using your application5. Screen shots of your application, as appropriate6. A brief summary of the activities and description of any problems you

    encountered