Recent articles:
Popular archives:
Java: A platform for platforms
Sun's reorg may seem promising to shareholders but it's also a scramble for position. The question now is whether Sun can,
or wants to, maintain its hold on Java technology. Especially with enterprise leaders like SpringSource and RedHat investing
heavily in Java's future as a platform for platforms
Also see:
Discuss: Tim Bray on 'What Sun Should Do'
The Google Earth client is a technological icon from this part of our century. Google Earth is not the first Earth client and is nearly the same as its lesser known predecessor, Keyhole. However, with the Google name behind it and the basic version free to the end user, it has market penetration and recognition—an interesting target to write for.
This article has one overriding mission: to show you how truly simple it is to send information to and from a servlet via the Earth client. With this degree of interaction, you can create imaginative services by applying basic Java programming skills.
| Licensing and competition |
|---|
| At the time of this writing, Google Earth is in beta form (version 3.0.0616). The license (found in the client's Help section) is commercial. If you wish for an equivalent open source example, I recommend concentrating your efforts on the excellent Nasa World Wind project. |
The Google Earth client parses XML in the form of Keyhole Markup Language (KML) version 2, a proprietary namespace. Numerous KML configurations are possible to affect a GUI. The difficulty in creating a well-balanced application is associated more with knowing the KML details than the subtleties of coding. A short list of KML entities includes:
For the sake of simplicity, in this article, I focus on the use of the folder, placement, and network-link elements. Further, I define a tour as a folder that contains a series of placements.
On installation of the Google software under Windows, the file extension KML and the MIME (Multipurpose Internet Mail Extensions) type "application/keyhole" are registered. This means that the client is activated by either a click on a KML file or a receipt, through TCP/IP, of a file with the "application/keyhole" MIME type.
If the KML text returned is:
<Folder><name>Hello World [127.0.0.1] </name></Folder>
Then the program will display the following:

Figure 1. GUI representation of the Hello World folder
To activate the Earth client, simply browse to the correct URL—for example, the HelloServlet whose source can be downloaded from Resources (http://localhost:8080/Tour/hello). Doing so activates the following doGet() method, which redirects to doPost(), allowing all Web browsers to view the results:
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
response.setContentType("application/keyhole");
PrintWriter out = response.getWriter();
String message ="<Folder><name>Hello World ["
+ request.getRemoteAddr()+ "]</name></Folder>";
out.println(message);
}
Do not be distracted by the code's simplicity. The method has powerful implications. A server can act as intermediary between different data types and Google Earth. One can imagine a situation where different XML dialects are involved for tour data, with the server performing Extensible Stylesheet Language transformations before passing on the finished response. Further, the server can choose which response to return, allowing for personalization. The document entity in KML allows for style definitions, and, by changing the style depending on IP address range, one can potentially differentiate between various customers.
To practice, we should begin working with Google Earth and exporting KML files. At the top of Google's program is the Add menu. From here, you may add placements, folders, and image overlays. You may then save the generated KML via the File menu. I strongly recommend editing the exported XML and seeing how your modifications affect Earth. Yes, let's play king of the world!
This section introduces an educationally orientated application: a program that teaches students names of cities and their relationships with a given land. We shall build a servlet that acts as a flashcard by sending a random city location back to the client. A placement expresses the city in KML. This placement has an embedded HTML link that points the user to a relevant and, one hopes, interesting Website. Thus, we now have user interaction involving both a Web browser and Google Earth.
The student can pull in the next placement by selecting Refresh from the menu that appears when the mouse hovers over the network link, as shown in Figure 2.

Figure 2. GUI representation of refreshing a network link to regenerate a placement (in this case, London)
The behind-the-scenes trick to our application is the use of a network-link entity. The network link loads a data file from http://location. Place the file on your desktop and double click it. Google Earth runs, and the KML fragment, shown below, loads from the server.
City.kml
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://earth.google.com/kml/2.0">
<NetworkLink>
<description>Refresh me</description>
<name>Random City</name>
<visibility>1</visibility>
<open>1</open>
<refreshVisibility>1</refreshVisibility>
<flyToView>1</flyToView>
<Url>
<href>http://location </href>
</Url>
</NetworkLink>
</kml>
The entity meanings within this configuration are:
visibility, which defines whether the network link can be seen
open, which explains whether the tag is to be expanded
refreshVisibility, which defines whether the refreshed placement's visibility overrides the user's choice
flyToView, which "flys" the user to the placement in the view window if set to 1Many of the entities are common across most root elements—description, for example. Note that the tag names are case sensitive, so be careful coding or you might have difficult-to-debug failures.
Personally, I find the relationship between the different tag values and their influence on interactions with the GUI not
always logical. Therefore, you may require play-around time in any new use of the KML fragments.
| Caution |
|---|
By default, the browsers Firefox, Opera, and Internet Explorer react differently to receiving a .kml extension from the Web. The most consistent method for activating the network-link file is to avoid the server for the initial
KML file, and allow users to download the file onto their desktops, where they can launch it themselves by double-clicking
on it. Another more adventurous approach is to place the KML file within a JSP (JavaServer Pages) page and allow the JSP page
to return the "application/keyhole" MIME type followed by the relevant KML fragment. For example, the city.jsp page is simply
the city.kml file, but with the content type modified and the XML Schema removed. The code starts with:
|
Back to the code, the servlet returns a placement with HTML coding in the description. Being a good XML citizen, we have placed
the HTML fragment within the <!CDATA[]]> delimiting tag, thus avoiding confusing the XML parsers:
<Placemark>
<name>London</name>
<description>
<![CDATA[<a href="http://www.visitlondon.com/choose_site/?OriginalURL=/">London</a>]]>
</description>
<address>London, UK</address>
<styleUrl>root://styleMaps#default+nicon=0x304+hicon=0x314</styleUrl>
<Point>
<coordinates>-0.1261969953775406,51.50019836425783,50</coordinates>
</Point>
</Placemark>
The three new entities seen in this placement are:
address, a logical tag to contain the address
styleUrl, which defines the graphic to be displayed in this case at the placeholder
Point/coordinates, cylindrical coordinates of the location
The servlet generates a random placement response via this code fragment:
manager.KMLRenderOfRandomPlacement();
Our whole application is elementary. The servlet does not keep track of state. Management class refactoring separates rendering
from data management. The Manager.java init method loads data into an array of property beans. Obviously, in a real application, where communication with a database
is necessary, a persistence management framework, such as iBATIS or Hibernate, would prove useful. The placement beans model
the data needed within the returned placement. The bean has the property point, which is a bean in itself. This allows later
expansion of the model as the developer learns more details of KML composition and what a point can achieve within the Earth
GUI.
The QuizServlet shown below is a thin wrapper around Manager.java; for every post or get request, the servlet returns a valid KML response.
QuizServlet.java
package test.google.earth.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.*;
import javax.servlet.ServletConfig;
import test.google.earth.manager.Manager;
public class QuizServlet extends HttpServlet
{
private Manager manager;
public void init(ServletConfig config) throws ServletException {
super.init(config);
this.manager= new Manager();
manager.init();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
response.setContentType("application/keyhole");
PrintWriter out = response.getWriter();
out.println(manager.KMLRenderOfRandomPlacement());
}
}
Manager.java
package test.google.earth.manager;
import java.util.Random;
import test.google.earth.bean.PlacementBean;
import test.google.earth.bean.PointBean;
public class Manager {
private PlacementBean[] cityArray;
private String styleURL;
private String open;
private Random generator;
private int idx;
public Manager(){}
public void init(){
this.styleURL="root://styleMaps#default+nicon=0x304+hicon=0x314";
this.open="1";
this.generator = new Random();
String[] coords = {"-0.1261969953775406,51.50019836425783,50",
"12.5,41.889999,50","4.889999,52.369998,0"};
String[] name = {"London","Italy","Amsterdam"};
String[] address={"London, UK","Rome, Italy","Amsterdam, Netherlands"};
String[] description={
"<a href=\"http://www.visitlondon.com/choose_site/?OriginalURL=/\">London</a>",
"<a href=\"http://www.roma2000.it/\">Rome</a>",
"<a href=\"http://www.uva.nl/\">University of Amsterdam</a>"};
this.idx=coords.length;
cityArray= new PlacementBean[coords.length];
//Init the array of placements
for (int i =0; i<coords.length;i++){
placementBean placementBean = new PlacementBean();
placementBean.setAddress(address[i]);
placementBean.setDescription(description[i]);
placementBean.setName(name[i]);
placementBean.setOpen(open);
placementBean.setStyleURL(styleURL);
pointBean pointBean = new PointBean();
pointBean.setCoordinate(coords[i]);
placementBean.setCoordinates(pointBean);
this.cityArray[i]=placementBean;
}
}
public synchronized PlacementBean nextRandomPlacement(){
return cityArray[ generator.nextInt( this.idx )];
}
public synchronized String KMLRenderOfRandomPlacement(){
return renderKMLPlacement(nextRandomPlacement());
}
private String renderKMLPlacement(PlacementBean pBean){
String klmString="<Placemark>\n"+
"\t<name>"+pBean.getName()+"</name>\n"+
"\t<description><![CDATA["+pBean.getDescription()+"]]></description>"+
"\t<address>"+pBean.getAddress()+"</address>\n"+
"\t<styleUrl>"+pBean.getStyleURL()+"</styleUrl>\n"+
"\t<Point>\n"+
"\t\t<coordinates>"+pBean.getCoordinates().getCoordinate()+"</coordinates>\n"+
"\t</Point>\n"+
"</Placemark>\n";
return klmString;
}
}
Adding remotely served graphics to the placements is straightforward. The styleUrl tag needs a link to the Web, e.g., http:/imageServer/image.gif. This allows the code to expand so the window's view renders
a placement with an image, such as a nation's flag, in the current application.
Looking further into this methodology, one could imagine a situation where the user has the opportunity to fill in a Web form while interacting with the Google Earth client. See Figure 3 for a viable definition of such an infrastructure.

Figure 3: Potential infrastructure for a form-based tour service
An Apache Web server sits in front of two servlets. The first is the form server that returns Web forms depending on the parameters sent. The second is the tour servlet that generates a list of placements to make up one tour enclosed in a folder. The tour server calculates the image URL, but the image itself is stored statically on the filesystem to improve performance.
The collaborations are as follows:
As you can see, with imagination, creation of functional and educationally rewarding applications is viable. However, we are still missing direct feedback from the client to the servlet on a periodic basis, not just when the student refreshes the placement. The next section drills down into this issue.
Archived Discussions (Read only)