Skip Headers
Oracle® Application Server MapViewer User's Guide
Release 10.1.3.1
B14036-03
  Go To Documentation Library
Home
Go To Product List
Solution Area
Go To Table Of Contents
Contents
Go To Index
Index

Previous
Previous
 
Next
Next
 

8 Oracle Maps

Oracle Maps is the name for a suite of technologies for developing high-performance interactive Web-based mapping applications. Oracle Maps is included with OracleAS MapViewer.

This chapter contains the following major sections:

8.1 Overview of Oracle Maps

Oracle Maps consists of the following main components:

The map cache server (map image caching engine) automatically fetches and caches map image tiles rendered by Oracle MapViewer or other Web-enabled map providers. It also serves cached map image tiles to the clients, which are Web applications developed using the Oracle Maps client API. The clients can then automatically stitch multiple map image tiles into a seamless large base map. Because the map image tiles are pre-generated and cached, the application users will experience fast map viewing performance.

The feature of interest (FOI) server (rendering engine) renders spatial feature layers managed by Oracle Spatial, as well as individual geospatial features of point, line, or polygon type that are created by an application. Such FOIs, which typically include both an image to be rendered and a set of associated attribute data, are then sent to the client where a user can interact with them. Unlike the cached image tiles, which typically represent static content, FOIs are dynamic and represent real-time database or application contents. The dynamic FOIs and the static cached base map enable you to build Web mapping applications.

The JavaScript mapping client is a browser side map display engine that fetches map content from the servers and presents it to client applications. It also provides customizable map-related user interaction control, such as map dragging and clicking, for the application. The JavaScript mapping client can be easily integrated with any Web application or portal.

8.1.1 Architecture for Oracle Maps Applications

Figure 8-1 shows the architecture of Web mapping applications that are developed using Oracle Maps.

Figure 8-1 Architecture for Oracle Maps Applications

Description of Figure 8-1 follows
Description of "Figure 8-1 Architecture for Oracle Maps Applications"

Referring to Figure 8-1, applications interact with the Oracle Maps architecture as follows:

  • The application is developed using JavaScript, and it runs inside the JavaScript engine of the Web browser.

  • The application invokes the JavaScript map client to fetch the map image tiles from the map cache server, and then it displays the map in the Web browser.

  • The application invokes the JavaScript map client to fetch dynamic spatial features from the FOI server and display them on top of the base map.

  • The JavaScript map client controls map-related user interaction for the application.

  • When the map cache server receives a map image tile request, it first checks to see if the requested tile is already cached. If the tile is cached, the cached tile is returned to the client. If the tile is not cached, the map cache server fetches the tile into the cache and returns it to the client. Tiles can be fetched either directly from the OracleAS MapViewer map rendering engine or from an external Web map services provider.

  • When the FOI server receives a request, it uses the OracleAS MapViewer map rendering engine to generate the feature images and to send these images, along with feature attributes, to the client.

8.1.2 Simple Example Using Oracle Maps

Figure 8-2 shows the interface of a simple application created using Oracle Maps. This example is shipped with MapViewer, and can be accessed at http://host:port/mapviewer/fsmc/sampleApp.html. To run this application, follow the instructions in http://host:port/mapviewer/fsmc/tutorial/setup.html to set up the database schema and the necessary map cache instances.

Figure 8-2 Application Created Using Oracle Maps

Description of Figure 8-2 follows
Description of "Figure 8-2 Application Created Using Oracle Maps"

The application shown in Figure 8-2 displays customers on the map. The map consists of two layers:

  • The base map layer displays the ocean, county boundaries, cities, and highways. The whole base map displayed in the Web browser consists of multiple map image tiles that are rendered by the map cache server.

  • The FOI layer displays customers as red dot markers on top of the base map. If the user clicks on the marker for a customer, an information window is displayed showing some attributes for that customer. The customer markers and attributes are rendered by the FOI server.

In addition to these two layers, a scale bar is displayed in the lower-left corner of the map, and a navigation panel is displayed in the upper-right corner.

The application user can use the mouse to drag the map. When this happens, new image tiles and FOIs are automatically fetched for the spatial region that the map currently covers. The user can also use the built-in map navigation tool to pan and zoom the image, and can show or hide the customers (red dot markers) by checking or unchecking the Show customers box.

Example 8-1 shows the complete source code for the simple application shown in Figure 8-2.

Example 8-1 Source Code for the Simple Application

<html>
<head>
<META http-equiv="Content-Type" content="text/html" charset=UTF-8">
<TITLE>A sample Oracle Maps Application</TITLE>
<script language="Javascript" src="jslib/loadscript.js"></script>
<script language=javascript>
var themebasedfoi=null
function on_load_mapview() 
{  
  var baseURL  = "http://"+document.location.host+"/mapviewer";
  // Create an MVMapView instance to display the map
  var mapview = new MVMapView(document.getElementById("map"), baseURL);
  // Add a base map layer as background.
  mapview.addBaseMapLayer(new MVBaseMap("mvdemo.demo_map"));   
  // Add a theme-based FOI layer to display customers on the map
  themebasedfoi = new MVThemeBasedFOI('themebasedfoi1','mvdemo.customers');
  themebasedfoi.setBringToTopOnMouseOver(true);
  mapview.addThemeBasedFOI(themebasedfoi);
  // Set the initial map center and zoom level
  mapview.setCenter(MVSdoGeometry.createPoint(-122.45,37.7706,8307));   
  mapview.setZoomLevel(4);    
  // Add a navigation panel on the right side of the map
  mapview.addNavigationPanel('east');
  // Add a scale bar
  mapview.addScaleBar();
  // Display the map.
  mapview.display();
}
function setLayerVisible(checkBox)
{
  // Show the theme-based FOI layer if the check box is checked and
  // hide the theme-based FOI layer otherwise.
  if(checkBox.checked)
    themebasedfoi.setVisible(true) ;
  else
    themebasedfoi.setVisible(false);
}
</script>
</head>
<body onload= javascript:on_load_mapview() >
<h2> A sample Oracle Maps Application</h2>
<INPUT TYPE="checkbox" onclick="setLayerVisible(this)" checked/>Show customers
<div id="map" style="width: 600px; height: 500px"></div> 
</body>
</html>

The components of this sample application and the process for creating a client application are described in Section 8.5.3.

8.1.3 How Map Content Is Organized

This section describes how the JavaScript client internally organizes various map contents when displayed a map inside a Web browser. An application typically places one master HTML DIV object on a Web page, and the JavaScript client adds various content layers inside this DIV object.

The map content displayed by the map client is organized by layers. When the application script invokes appropriate map client API, map layers are created inside a map container. The map container is a user-defined HTML DIV object. You can customize the size and the positioning of the map container inside the Web page. Figure 8-3 shows the layout of the map layers.

Figure 8-3 Layers in a Map

Description of Figure 8-3 follows
Description of "Figure 8-3 Layers in a Map"

As shown in Figure 8-3, there are five different types of map content layers: base map tiles, theme-based FOI, user-defined FOI or redline, information window, and fixed figures. All layers except the fixed figures layer are moved as a whole when the user drags the map. These movable layers are automatically updated by the map client when the map is dragged or zoomed. (The fixed figures layer is never moved.).

8.1.3.1 Base Map Layers

A typical Oracle Maps application has at least one base map layer, which assembles and displays pregenerated map image tiles from a map cache instance. The base map displays static map content that does not change very often, and it is typically used as the background map by the client application. For example, in the sample application described in Section 8.1.2 and illustrated in Figure 8-2, the ocean, county boundaries, cities, and highways are all displayed as a base map layer. Only limited user interaction, such as map dragging, can be performed with a base map layer.

A map cache instance is usually associated with a MapViewer base map, and is managed by the MapViewer server; however, you can configure a map cache instance to cache map image tiles from an external (non-MapViewer) map provider.

Base map layers are always placed at the bottom of the layer hierarchy. These layers display static and background map contents. When multiple such layers from different map cache instances are included, they must all have the same coordinate system and zoom level definitions.

Internally, the map tile layers are usually larger than the size of the map DIV container window. This allows additional tiles to be fetched and cached by the browser. As a result, these tiles will be immediately visible when the map layers are dragged around by the user.

8.1.3.2 Theme-Based FOI Layers

There can be one or more theme-based FOI layers. Each theme-based FOI layer consists of a collection of interactive FOIs that meet certain query criteria defined in a MapViewer predefined theme. FOIs can be points, lines, or polygons. For example, all stores with a sales volume greater than $100,000 can be displayed as a point theme-based FOI layer.

Users can interact with the FOIs by moving the mouse over them or clicking on them. The application can customize how the map client reacts to such user interaction.

All features (geographic and non-geographic) of a theme-based FOI layer are stored in the database. Features are queried and rendered by the FOI server when client applications request them. The query window for the theme-based FOI layers can be customized to be larger than the map DIV window, so that it gives some extra room for dragging the map without refreshing the theme-based FOI layers from server. For more information about theme-based FOI layers, see Section 8.3.1.

8.1.3.3 User-Defined FOI Layers

A user-defined FOI is an interactive feature defined on the client side. The FOI can be a point, line, or polygon feature. Users can interact with a user-defined FOIs in the same way they can with a theme-based FOIs. However, in contrast with a theme-based FOI layer which is rendered as a collection of features, each user-defined FOI is requested and rendered individually. All attributes of the user-defined FOI, including the geometry representation and rendering style, must be provided by the application. For example, a route geometry based on user specified start and end addresses should be displayed as a user-defined line FOI on the map.

The handling of user-defined FOI layers depends on Web browser in which the application is running:

  • With Microsoft Internet Explorer, all user-defined individual FOIs added by the application are placed inside a layer directly above the theme-based FOI layers. There can be at most one such layer.

  • With Opera and Mozilla-based browsers such as Netscape and Firefox, all user-defined individual FOIs are placed inside two layers, one for point features and the other for non-point features such as polylines and polygons. The non-point feature layer is placed under the point feature layer.

8.1.3.4 Information Window Layer

An information window is a small pop-up window that displays customizable content in the map. All information windows, when displayed, are placed inside a layer directly above the user-defined individual FOI layer or layers. There can be at most one information window layer.

8.1.3.5 Fixed Figures Layer

The topmost layer contains any fixed figures, which are immovable elements such as copyright notes, a scale bar, a navigation panel, and user-defined map decoration features. (A user-defined map decoration feature is an application defined element that can contain any custom HTML content, such as a map title or a custom control button.) The fixed figures layer is displayed on top of everything else, and it is not moved when the user drags the map.

8.2 Map Cache Server

The map cache server is a map image caching engine that caches and serves pregenerated, fixed-size map image tiles. It is implemented as a Java servlet that is part of the OracleAS MapViewer server. The map cache server accepts requests that ask for map image tiles specified by tile zoom level and tile location (mesh code), and it sends the requested tiles back to clients.

Figure 8-4 shows the basic workflow of the map cache server.

Figure 8-4 Workflow of the Map Cache Server

Description of Figure 8-4 follows
Description of "Figure 8-4 Workflow of the Map Cache Server"

As shown in Figure 8-4, when the map cache server receives a request for a map tile, it searches for the tile in the cache storage system. If the tile is cached, the map cache server sends the tile to the client. If the tile is not cached, the map cache server fetches the tile, saves in the cache, and sends it to the client.

You can use the MapViewer administration tool to manage the map cache server.

8.2.1 Map Cache Server Concepts

This section explains map cache server concepts that you need to know to be able to use Oracle Maps effectively.

8.2.1.1 Map Cache Instances and Base Map Sources

Each base map is managed by a map cache instance inside the map cache server. The map cache instance fetches and stores the map image tiles that belong to the base map and returns map image tiles to the client. The map cache server can have multiple map cache instances, each of which manages a different base map.

Each base map can have multiple predefined zoom levels. Each zoom level is assigned a zoom level number ranging from 0 to n-1, where n is the total number of zoom levels. Zoom level 0 is the most zoomed out level and zoom level n-1 is the most zoomed in level.

The base map is evenly divided into same-sized small map image tiles on each zoom level. Clients specify a map tile by its zoom level and tile mesh code.

A base map can come from two different types of sources:

  • Internal MapViewer base maps rendered by the MapViewer map rendering engine. A MapViewer base map consists of a set of predefined themes and must be predefined in the database view USER_SDO_USER_MAPS.

  • Maps rendered by an external Web map services providers. An external Web map services provider is a server that renders and serves maps upon client requests over the web. If you properly configure an adapter that can fetch maps from the external map services provider, the map cache instance can fetch and cache map tiles generated by the external map services provider. (A MapViewer instance other than the MapViewer inside which the Map Cache Server is running is also considered an external map services provider.)

8.2.1.2 Storage of Map Image Tiles

Oracle Maps uses the local file system to store cached image tiles. You can customize the path that is used for this storage as part of the map cache server configuration settings.

8.2.1.3 Coordinate System for Map Tiles

Map images are cached and managed by Map Cache Server as small same-size rectangular image tiles. Currently we support tiling on any two-dimensional Cartesian coordinate system. A geodetic coordinate system can also be supported when it is mapped as if it is a Cartesian coordinate system, where longitude and latitude are treated simply as two perpendicular axes, as shown in Figure 8-5.

Figure 8-5 Tiling with a Longitude/Latitude Coordinate System

Description of Figure 8-5 follows
Description of "Figure 8-5 Tiling with a Longitude/Latitude Coordinate System"

On each zoom level, the map tiles are created by equally dividing the whole map coordinate system along the two dimensions (X and Y, which inFigure 8-5 represent latitude and longitude). The map cache server needs this dimensional information of the map coordinate system in order to create map image tiles, and therefore you must include this information in the map cache instance configuration settings.

The whole map coordinate system can be represented by a rectangle, and its boundary is specified by (Xmin, Ymin) and (Xmax, Ymax), where Xmin is the minimum X value allowed in the coordinate system, Ymin is the minimum Y value allowed, Xmax is the maximum X value allowed and Ymax is the maximum Y value allowed. In Figure 8-5, Xmin is –180, Ymin is –90, Xmax is 180, and Ymax is 90.

You must also specify the spatial referencing ID (SRID) of the coordinate system to enable the map cache server to calculate map scales.

8.2.1.4 Tile Mesh Codes

Each map tile is specified by a mesh code, which is defined as a pair of integers (Mx, My), where Mx specifies the X dimension index of the tile and My specifies the Y dimension index of the tile. If the tile is the ith tile on X dimension starting from Xmin, then Mx should be i-1. If the tile is the jth tile on Y dimension starting from Ymin, then My should be j-1. Figure 8-6 shows the mesh codes of the tiles on a map.

Figure 8-6 Tile Mesh Codes

Description of Figure 8-6 follows
Description of "Figure 8-6 Tile Mesh Codes"

The JavaScript map client automatically calculates which tiles it needs for displaying the map in the Web browser, and it sends requests with the mesh codes to the server. Mesh codes are transparent to the application, and application developers do not need to deal with mesh codes directly.

8.2.1.5 Tiling Rules

You must create tiling rules that determine how the map is divided and how tiles are created. The map cache server uses these tiling rules to divide the map into small map image tiles that are stored in the tile storage system. These rules are also used by the JavaScript map client.

Because all tiles on a given zoom level are the same size, the map cache server needs to know the following information to perform the tile division:

  • The map tile image size (width and height), specified in screen pixels. This is the physical size of the tile images.

  • The tile size specified according to the map coordinate system. For example, if the map uses a geodetic coordinate system, the tile width and height should be defined in degrees. The size can be specified either explicitly by tile width and height or implicitly by map scale. (Map scale, combined with tile image size, can be used to derive the tile width and height according to the map coordinate system.)

The preceding information constitutes the tiling rule for a given zoom level. Each zoom level must have its own tiling rule. You must define the tiling rules when you specify the configuration settings for the map cache server, as described in Section 8.2.2.

8.2.2 Map Cache Server Configuration

Map cache server configuration settings are stored in local configuration files and in database views. You can customize these settings.

8.2.2.1 Global Map Cache Server Configuration

Global map cache server settings, such as logging options and the default cache storage directory, are stored in the MapViewer configuration file mapViewerConfig.xml, which is under the directory $MAPVIEWER_HOME/web/WEB-INF/conf.

The map cache server configuration settings are defined in element <map_cache_server> inside the top-level <mapperConfig> element, as shown in the following example:

<map_cache_server>
   <logging 
      log_level="info" 
      log_thread_name="false" 
      log_time="true">
     <log_output name="System.err"/>
    <log_output name="../log/mapcacheserver.log" />
   </logging>
   <cache_storage default_root_path="/scratch/mapcache/"/>
</map_cache_server>

The <logging> element specifies the logging options. It has the same syntax and options as the <logging> element for MapViewer in the mapViewerConfig.xml file, as described in Section 1.5.2.1. However, because the logging information generated by the map cache server is not written to the MapViewer log file, if you want this information to be logged, you must specify the <logging> element in the <map_cache_server> element.

The <cache_storage> element specifies the map tiles storage settings. The default_root_path attribute specifies the default file system directory under which the cached tile images are to be stored. If the default root directory is not set or not valid, the default root directory is $MAPVIEWER_HOME/web/mapcache. A subdirectory under this directory will be created and used for a map cache instance if the cache instance configuration does not specify the map tiles storage directory for itself. The name of the subdirectory will be the same as the name of the cache instance.

8.2.2.2 Map Cache Instance Configuration

The configuration settings for a cache instance are stored in the USER_SDO_CACHED_MAPS metadata view. You should normally not manipulate this view directly, but should instead use the MapViewer administration tool, which uses this view to configure map cache instances.

Each database user (schema) has its own USER_SDO_CACHED_MAPS view. Each entry in this view stores the configuration settings for one map cache instance. If the cache instance is an internal MapViewer cache instance, the base map associated with the cache instance must be defined in the same database schema where the cache instance configuration settings are stored.

The map cache server obtains the map source configuration by querying the USER_SDO_CACHED_MAPS view using the database connections specified by MapViewer data sources. This happens when the map cache server is started or a new data source is added to MapViewer as the result of a MapViewer administration request.

The USER_SDO_CACHED_MAPS view has the columns listed in Table 8-1.

Table 8-1 USER_SDO_MAPS View

Column Name Data Type Description

NAME

VARCHAR2

Unique name of the cached map source

DESCRIPTION

VARCHAR2

Optional descriptive text about the cached map source

TILES_TABLE

VARCHAR2

(Not currently used)

IS_ONLINE

VARCHAR2

YES if the map cache instance is online, or NO if the map cache instance is offline. When a tile is missing from the cache and the map cache instance is online, the map cache server will fetch the tile and return the fetched tile to the client. When a tile is missing and the map cache instance is offline, the map cache server will not fetch the tile but will return a blank image to the client.

IS_INTERNAL

VARCHAR2

YES if the map source is an internal map source, or NO if the map source is an external map source

DEFINITION

CLOB

XML definition of the map cache instance, as described later in this section.

BASE_MAP

VARCHAR2

Name of the cached MapViewer base map, if the map source is an internal map source

MAP_ADAPTER

BLOB

The jar file that contains the adapter Java classes of the external map services provider, as described later in this section.


For the DEFINITION column, the map source definition has the following general format:

  <cache_instance 
     image_format ="tile-image-format">
    <internal_map_source 
      base_map="name-of-MapViewer-base-map"
      bgcolor="base-map-background-color"/>
    </internal_map_source>
    <external_map_source 
       url="external-map-service-url" 
       adapter_class="name-of-adapter-class"
       proxy_host=" proxy-server-host "
       proxy_port="proxy-server-port"
       timeout="request-timeout"
       request_method="http-request-method: 'GET'|'POST'">
      <properties>
        <property name="property-name" value="property-value"/>
        …
      </properties>
    </external_map_source>
    <cache_storage 
       root_path="disk-path-of-cache-root-directory"
    </cache_storage>
    <coordinate_system
       srid="coordinate-system-srid" 
       minX="minimum-allowed-X-value" 
       maxX="maximum-allowed-X-value"
       minY="minimum-allowed-Y-value" 
       maxY="maximum-allowed-Y-value">
    </coordinate_system>
    <tile_image
       width="tile-image-width-in-screen-pixels" 
       height="tile-image-height-in-screen-pixels" >
    </tile_image>
    <cache_bound>
       <coordinates> … </coordinates>
    </cache_bound>
    <zoom_levels
       levels="number-of-zoom-levels"
       min_scale="map-scale-at-highest-zoom-level" 
       max_scale="map-scale-at-lowest-zoom-level"
       min_tile_width="tile-width-specified-in-map-data-units-at-
                       tile-width-specified-in-map-data-units-at-" 
       max_tile_width="tile-width-specified-in-map-data-units-at-
                       lowest-zoom-level">
      <zoom_level 
         description="zoom-level-description"
         level_name="zoom-level-name"
         scale="map-scale-of-zoom-level"
         tile_width ="tile-width-specified-in-map-data-units"
         tile_height ="tile-height-specified-in-map-data-units">
        <cache_bound>
          <coordinates> … </coordinates>
        </cache_bound>
      </zoom_level>
      …
    </zoom_levels>
  </cache_instance>

Example 8-2 shows the XML definition of an internal map cache instance, and Example 8-3 shows the XML definition of an external map cache instance. Explanations of the <cache_instance> element and its subelements follow these examples.

Example 8-2 XML Definition of an Internal Map Cache Instance

<?xml version = '1.0'?>
<!-- XML definition of an internal map cache instance.
-->
<mapcache_config>
   <cache_instance image_format="PNG">
      <internal_map_source base_map="demo_map"/>
      <cache_storage root_path="/scratch/mapcache/"/>
      <coordinate_system 
         srid="8307"
         minX="-180" maxX="180" 
         minY="-90" maxY="90"/>
      <tile_image width="250" height="250"/>
      <zoom_levels>
         <zoom_level description="continent level" scale="10000000"/>
         <zoom_level description="country level" scale="3000000"/>
         <zoom_level description="state level" scale="1000000"/>
         <zoom_level description="county level" scale="300000"/>
         <zoom_level description="city level" scale="100000"/>
         <zoom_level description="street level" scale="30000"/>
         <zoom_level description="local street level" scale="10000"/>
      </zoom_levels>
   </cache_instance>
</mapcache_config>

Example 8-3 XML Definition of an External Map Cache Instance

<?xml version = '1.0'?>
<!-- XML definition of an external map cache instance.
-->
<mapcache_config>
   <cache_instance image_format="PNG">
      <external_map_source  
         url="http://elocation.oracle.com/elocation/lbs" 
         adapter_class="mcsadapter.MVAdapter">
         <properties>
            <property name="data_source" value="elocation"/>
            <property name="base_map" value="us_base_map"/>
         </properties>
      </external_map_source>
      <cache_storage root_path="/scratch/mapcache"/>
      <coordinate_system 
         srid="8307" 
         minX="-180" maxX="180" 
         minY="-90" maxY="90"/>
      <tile_image width="250" height="250"/>
     <!—
         The following <zoom_levels> element does not have any 
         <zoom_level> element inside it. But since it has its levels, 
         min_scale and max_scale attributes set, map cache server will 
         automatically generate the <zoom_level> elements for the 10 
         zoom levels.
      -->
      <zoom_levels levels="10" min_scale="5000" max_scale="10000000" />
   </cache_instance>
</mapcache_config>

The top-level element is <cache_instance>. The image_format attribute specifies the tile image format; the currently supported values for this attribute are PNG, GIF, and JPG. PNG and GIF images are generally better for vector base maps, while JPG images are generally better for raster base maps, such as satellite imagery, because of a better compression ratio. Currently, only tile images in PNG format can have transparent background.

The <internal_map_source> element is required only if the map cache instance manages map tiles rendered by the local MapViewer instance. The base_map attribute is required and specifies the predefined MapViewer base map that is cached by the map cache instance; its value should match an entry in the BASE_MAP column in the USER_SDO_CACHED_MAPS view. The bgcolor attribute is optional and specifies the background color of the base map. If the value of this attribute is set to NONE, the background will be transparent. (Currently MapViewer can only render transparent PNG map tiles.)

The <external_map_source> element is required only if the map cache instance manages map tiles rendered by an external map services provider. This element has the following attributes:

  • The url attribute is required and specifies the map service URL from which the map tiles can be fetched (for example, http://myhost/mapviewer/omserver).

  • The adapter_class attribute is required and specifies the full name of the map adapter class, including the package names (for example, mcsadapter.MVAdapter).

  • The proxy_host and proxy_port attributes are needed only if the external map provider server must be accessed through a proxy server; these attributes specify the host name and port number, respectively, of the proxy server. If proxy_host is specified as NONE, all map tile requests will be sent directly to the remote server without going through any proxy server. If proxy_host is omitted or specifies an empty string, the global MapViewer proxy setting defined in the mapViewerConfig.xml file will be used when map tile requests are sent.

  • The timeout attribute is optional and specifies the number of milliseconds for which the map cache server must wait for an external map tile image before giving up the attempt. The default timeout value is 15000.

  • The request_method attribute is optional and the HTTP request method for sending map tile requests; its value can be POST (the default) or GET.

The <properties> element in the <external_map_source> element can include multiple <property> elements, each of which specifies a user-defined parameter for use by the map adapter when it fetches map tiles. The same map source adapter can use different set of parameters to fetch different base maps. For example, the sample MapViewer adapter mcsadapter.MVAdapter shipped with MapViewer accepts parameters defined as follows:

<properties>
   <property name="data_source" value="elocation"/>
   <property name="base_map" value="us_base_map"/>
</properties>

However, by changing the value attribute values, you can use this adapter to fetch a different base map from the same data source or a different data source.

The <cache_storage> element specifies cache storage settings for the cache instance. The optional root_path attribute specifies the file system directory to be used as the root directory of the cache instance storage. If this attribute is omitted or invalid, the default root directory defined in the mapViewerConfig.xml file is used.

The <coordinate_system> element specifies the map coordinate system, and it has several required attributes. The srid attribute specifies the spatial reference ID of the coordinate system. The minX attribute specifies the lower bound of the X dimension; the minY attribute specifies the lower bound of the Y dimension; the maxX attribute specifies the upper bound of the X dimension; and the maxY attribute specifies the upper bound of the Y dimension. For the standard longitude/latitude (WGS 84) coordinate system, the srid value is 8307; and the minX, minY, maxX, and maxY values are -180, -90, 180, and 90, respectively.

For an internal map cache instance, the map coordinate system can be different from the data coordinate system. If the two are different, the map cache server transforms the map data into the coordinate system defined in the <coordinate_system> element and renders map tile images using this coordinate system.

The <tile_image> element specifies the tile image size settings, and it has the following required attributes: width specifies the width of the tile images in screen pixels, and height specifies the height of the tile images in screen pixels.

The optional <cache_bound> element specifies the bounding box of the cached map tiles. Map cache instance only fetches tiles inside this box and will return a blank tile if the requested tile is outside this box. The bounding box is specified by a rectangle in the map data coordinate system. The rectangle is specified by a <coordinates> element in the following format:

<coordinates>minX, minY, maxX, maxY</coordinates>

The default cache bounding box is the same bounding box specified in the <coordinate_system> element.

The <zoom_levels> element specifies the predefined zoom levels. Only image tiles at predefined zoom levels will be cached and served by the map cache instance. The <zoom_levels> element can have multiple <zoom_level> elements, each of which specifies one predefined zoom level. If there are no <zoom_level> elements, the map cache server automatically generates the <zoom_level> elements by using the following attributes inside the <zoom_levels> element. (These attributes can be omitted and will be ignored if any <zoom_level> elements exist.)

  • levels specifies the total number of zoom levels.

  • min_scale specifies the scale of map images at the highest (zoomed in the most) zoom level.

  • max_scale specifies the scale of map images at the lowest (zoomed out the most) zoom level.

  • min_tile_width specifies the width of map tiles at the highest zoom level. The width is specified in map data units.

  • max_tile_width specifies the width of the map tiles at the lowest zoom level. The width is specified in map data units.

For the map cache server to be able to generate the definitions of individual zoom levels automatically, you must specify either of the following combinations of the preceding attributes:

  • levels, min_scale, and max_scale

  • levels, min_tile_width, and max_tile_width

When the zoom levels are defined this way, the map cache server automatically derives the definition of all the individual zoom levels and updates the XML definition with the <zoom_level> elements generated for the zoom levels. You can then make adjustments to each zoom level if you want.

Each zoom level is assigned a zoom level number by the map cache server based on the order in which the zoom levels are defined. The first zoom level defined in the <zoom_levels> element is zoom level 0, the second zoom level is zoom level 1, and so on. These zoom level numbers are used in the tile requests to refer to the predefined zoom levels.

The <zoom_level> element specifies a predefined zoom level, and it has several attributes. The description attribute is optional and specifies the text description of the zoom level. The level_name attribute is optional and specifies the name of the zoom level. The scale attribute specifies the map scale of the zoom level; it is required if the attributes tile_width and tile_height are not defined. The tile_width and tile_height attributes specify the tile width and height, respectively, in map data units. The fetch_larger_tiles attribute is optional and specifies whether to fetch larger map images instead of the small map image tiles; a value of TRUE (the default) means that larger map images that may consist multiple map tiles will be fetched and broken into small map image tiles, which might save network round trips between the map cache server and the map services provider.

In the <zoom_level> element, you must specify either the scale attribute or both the tile_width and tile_height elements.

The <cache_bound> element within the <zoom_level> element optionally specifies the bounding box of the cached map tiles for the zoom level. The map cache instance only fetches tiles inside this box and returns a blank tile if the requested tile is outside this box. The bounding box is specified by a rectangle specified in map data coordinate system. The rectangle is specified by a <coordinates> element (explained earlier in this section) If you specify the <cache_bound> element within the <zoom_level> element, it overrides the overall cache bounding box settings specified by the <cache_bound> element that is above it in the XML hierarchy.

8.2.3 External Map Source Adapter

An external map source adapter is the interface between a map cache instance and an external map services provider. When a map image tile needs to be fetched from the external map services provider, the map cache instance calls the adapter with information about the zoom level, size, and location of the tile. The adapter then constructs a provider-specific request, sends the request to the external map services provider, and return the resulting image tile to the map cache instance.

The external map source adapter is a Java class that must extends the abstract Java class oracle.mapviewer.share.mapcache.MapSourceAdapter, which is defined as follows:

public abstract class MapSourceAdapter
{
   public abstract String getMapTileRequest(TileDefinition tile);
   public byte[] getTileImageBytes(TileDefinition tile) ;
   public Properties getProperties() ;
}

An adapter that extends this class must implement the following method:

  • public String getMapTileRequest(TileDefinition tile)

    This method should implement the logic to construct the HTTP request string that can be sent to the map services provider to fetch the map image tile. For example, if the URL of a map tile is http://myhost/mymapserver?par1=v1&par2=v2&par3=v3, the HTTP request string returned by this method should be par1_v1&par2=v2&par3=v3.

    When the map cache server cannot find a specific map tile, it calls the getTileImageBytes method to fetch the binary data of the tile image, and that method calls the getMapTileRequest method to construct the map tile request before fetching the tile. The getMapTileRequest method takes one parameter: a TileDefinition object that specifies the zoom level, bounding box, image size and image format of the requested tile. This method returns the HTTP request string.

The map source adapter also inherits all methods implemented in class MapSourceAdapter. Among them, the following methods are more important than the others:

  • public byte[] getTileImageBytes(TileDefinition tile)

    This method fetches the actual binary map tile image data from the external map service provider. This method is already implemented. It calls the abstract method getMapTileRequest to construct the map tile request and sends the request to the external map services provider. If the map tiles cannot be fetched by sending HTTP requests, you can override this method to implement the appropriate logic to fetch an image tile from the map source. This method takes one parameter: a TileDefinition object that specifies the zoom level, bounding box, image size, and image format of the requested tile. This method returns the binary tile image data encoded in the image format specified in the map cache instance configuration settings.

  • public Properties getProperties()

    This method returns the provider-specific parameters defined in the map cache instance configuration settings explained in Section 8.2.2.2.

The MapSourceAdapter and TileDefinition classes are packaged inside mvclient.jar, which can be found under the directory $MAPVIEWER_HOME/web/WEB/lib.

Example 8-4 shows an external map source adapter.

Example 8-4 External Map Source Adapter

/**
 * This is a sample map source adapter that can be used to fetch map 
 * tiles from an OracleAS MapViewer instance.
 */
package mcsadapter ;
 
import java.awt.Dimension;
import java.net.URL;
import java.util.Properties;
import oracle.lbs.mapclient.MapViewer;
import oracle.lbs.mapcommon.MapResponse;
import oracle.mapviewer.share.mapcache.*;
 
/**
 * The map source adapter must extend class
 * oracle.lbs.mapcache.cache.MapSourceAdapter.
 */
 
public class MVAdapter extends MapSourceAdapter
{
  /**
   * Gets the map tile request string that is to be sent to the map 
   * service provider URL.
   * @param tile tile definition
   * @return request string
   */
  public String getMapTileRequest(TileDefinition tile)
  {
    // Get map source specified parameters
    Properties props = this.getProperties() ;
    String dataSource = props.getProperty("data_source") ;
    String baseMap = props.getProperty("base_map") ;
    // Use oracle.lbs.mapclient.MapViewer to construct the request string
    MapViewer mv = new MapViewer(this.getMapServiceURL()) ;
    mv.setDataSourceName(dataSource);
    mv.setBaseMapName(baseMap);
    mv.setDeviceSize(new Dimension(tile.getImageWidth(), 
                                   tile.getImageHeight()));
    mv.setCenterAndSize(tile.getBoundingBox().getCenterX(), 
                        tile.getBoundingBox().getCenterY(),
                        tile.getBoundingBox().getHeight());
    int format = MapResponse.FORMAT_PNG_STREAM ;
    String req = null ;
    switch(tile.getImageFormat())
    {
      case TileDefinition.FORMAT_GIF:
        mv.setImageFormat(MapResponse.FORMAT_GIF_URL);
        req = mv.getMapRequest().toXMLString().replaceFirst(
                        "format=\"GIF_URL\"", "format=\"GIF_STREAM\"") ;
        break ;
      case TileDefinition.FORMAT_PNG:
        mv.setImageFormat(MapResponse.FORMAT_PNG_URL);
        req = mv.getMapRequest().toXMLString().replaceFirst(
                        "format=\"PNG_URL\"", "format=\"PNG_STREAM\"") ;
        break ;
      case TileDefinition.FORMAT_JPEG:
        mv.setImageFormat(MapResponse.FORMAT_JPEG_URL);
        req = mv.getMapRequest().toXMLString().replaceFirst(
                        "format=\"JPEG_URL\"", "format=\"JPEG_STREAM\"");
        break ;
    }
    
    byte[] reqStr = null ;
    try
    {
      reqStr = req.getBytes("UTF8") ;
    }
    catch(Exception e)
    {}
    // Return the request string.
    return "xml_request="+ new String(reqStr);
  }
}

Example 8-5 shows the implementation of the MapSourceAdapter.getTileImageBytes method.

Example 8-5 MapSourceAdapter.getTileImageBytes Implementation

/**
 * Fetches the map image tile from the external map service provider by 
 * sending the HTTP map tile request to the map service provider, and 
 * return the binary tile image data. You can rewrite this method so that 
 * the adapter can fetch the tile from an external map service provider 
 * that does not accept HTTP requests at all. 
 * @param tile the tile definition
 * @return the binary tile image data. 
 * @throws Exception
 */
public byte[] getTileImageBytes(TileDefinition tile)
  throws Exception
{
  // construct request string
  String request = getMapTileRequest(tile) ;
  
  if(request == null) 
  {
    throw new Exception("Null map tile request string in map source adapter!") ;
  }
 
  // set proxy settings
    Proxy proxy = null ;
 
  /* If the proxyHost is "NONE", the request is sent directly to the 
   * external server. If the proxyHost is a valid host, that host will 
   * be used as the proxy server. If the proxyHost is empty of omitted,  
   * the global proxy setting in mapViewerConfig.xml will be in effect.
   */
  boolean noProxy = "NONE".equalsIgnoreCase(getProxyHost()) ;
  if(getProxyHost()!=null && !noProxy)
  {
    SocketAddress addr = new InetSocketAddress(proxyHost, proxyPort);
    proxy = new Proxy(Proxy.Type.HTTP, addr);
  }
    
  // send the request and get the tile image binary  
  PrintWriter wr = null ;
  BufferedInputStream bis = null;
  try 
  {
    String urlStr = mapServiceURL ;
    if("GET".equalsIgnoreCase(httpMethod))
      urlStr = mapServiceURL + "?" + request ;
    log.finest("http "+httpMethod+": "+urlStr);
      
    URL url = new URL(urlStr);
    // Open a URL connection based on current proxy setting
    URLConnection conn = 
      proxy!=null? url.openConnection(proxy):
                   (noProxy? url.openConnection(Proxy.NO_PROXY):
                             url.openConnection()) ;
    conn.setConnectTimeout(timeOut);
    if("GET".equalsIgnoreCase(getHTTPMethod()))
      conn.connect();
    else
    {
      conn.setDoOutput(true);
      wr = new PrintWriter(conn.getOutputStream());
      wr.print(request);
      wr.flush();
      wr.close();
      wr = null ;
    }
    bis = new BufferedInputStream(conn.getInputStream());
    byte[] result = toBytes(bis) ;
    bis.close();
    bis = null ;
    return result;
  }
  catch(Exception ioe) 
  {
    throw new Exception("Failed to fetch external map tile.", ioe);
  }
  finally 
  {
    try 
    {
      if(bis != null) 
      {
        bis.close();
        bis = null;
      }
      if(wr != null) 
      {
        wr.close();
        wr = null;
      }
    }
    catch(IOException ioee) 
    {
      throw ioee;
    }
  }
} 

8.3 Feature of Interest (FOI) Server

A feature of interest (FOI) is a business entity or geographical feature that can be manipulated or interacted with by a JavaScript map client running in the Web browser. FOI data is dynamically displayed and is not part of the base map. FOIs can be any spatial geometry type, such as points, line strings, and polygons. The ability to search, browse, inspect, and interact with FOIs is essential for location-based services.

The FOI server is a Java servlet running inside MapViewer. It responds to FOI requests from a JavaScript map client by querying the database, rendering FOI images, and sending the FOI images along with FOI attribute data to the client. The JavaScript map client displays the FOI images to the end user and provides interaction with the images.

The FOI server accepts the following types of FOI requests: theme-based and user-defined. Each type of FOI request returns a data layer appropriate for the request type.

8.3.1 Theme-Based FOI Layers

A theme-based FOI layer is a collection of spatial features that have similar characteristics and that are stored in the database. The client fetches a theme-based FOI layer by sending a theme-based FOI layer request to the FOI server. The result of this request is a collection of FOI data entries that meets certain query criteria. Each FOI data entry contains the FOI image, as well as FOI attributes that can be used by the JavaScript map client to implement client-side interactivity.

A theme-based FOI layer is based on a predefined MapViewer theme (see Section 8.3.1.1) or a dynamic JDBC query theme (see Section 8.3.1.3, which defines all information necessary for FOI data rendering. The information includes the table in which the geometry features are stored, the criteria to use during the database query, the attributes that are part of the FOI data, and the style to use when rendering the FOI images. Predefined themes can be defined and configured using the Map Builder tool, which is described in Chapter 9.

8.3.1.1 Predefined Theme-Based FOI Layers

When the client requests FOI data using a predefined theme-based FOI request, it must specify the name of a predefined theme, the scale of the feature images, and the query window used to query the geometry features. The theme name must be defined by the application, while the scale of the feature images and the query window are automatically calculated by the JavaScript map client.

For example, a predefined theme named CUSTOMERS could be defined on a table named CUSTOMERS, which has the following definition:

SQL> DESCRIBE CUSTOMERS
 Name                              Null?  Type
 --------------------------------- ------ ----------------------------
 NAME                                      VARCHAR2(64 CHAR)
 CITY                                      VARCHAR2(64 CHAR)
 COUNTY                                    VARCHAR2(64 CHAR)
 STATE                                       VARCHAR2(64 CHAR)
 LOCATION                                  SDO_GEOMETRY
 SALES                                     NUMBER

The LOCATION column is the spatial column that is used for rendering the customer markers.

The XML styling rules for the CUSTOMERS theme are shown in Example 8-6.

Example 8-6 XML Styling Rules for Predefined Theme Used for FOI Layer

<?xml version="1.0" standalone="yes"?>
<styling_rules>
  <hidden_info>
    <field column="CITY" name="City"/>
    <field column="SALES" name="Sales"/>
  </hidden_info>
  <rule>
    <features style="M.CIRCLE"> </features>
    <label column="NAME" style="T.TEXT"> 1 </label>
  </rule>
</styling_rules>

The styling rules in Example 8-6 specify the following. To see how these specifications affect the map display, see Figure 8-2, "Application Created Using Oracle Maps" in Section 8.1.2.

  • The marker style M.CIRCLE is used to render the customers.

  • The NAME column is used as the labeling attribute (label column="NAME"). The value in the NAME column (the name of the customer) is included in the information window that the JavaScript map client displays when the user moves the mouse over the customer marker.

  • The information window also includes the values in columns specified in the <hidden_info> element (CITY and SALES in this example) for that customer. Each <field> element specifies two attributes: column to identify the database column and name to identify a text string to be used in the information window.

8.3.1.2 Templated Predefined Themes

The predefined MapViewer theme can be a standard predefined theme or a templated predefined theme. Both types of predefined themes are defined in the USER_SDO_THEMES view. However, the query conditions of a standard predefined theme are fixed, whereas the query conditions of a templated predefined theme can contain dynamic binding variables whose values can be changed when the theme request is issued.

Example 8-7 shows the XML styling rules for a templated predefined theme that uses two binding variables (with the relevant text shown in bold in the <features> element).

Example 8-7 XML Styling Rules for a Templated Predefined Theme

<?xml version="1.0" standalone="yes"?>
<styling_rules>
  <hidden_info>
    <field column="NAME" name="Name"/>
    <field column="CITY" name="City"/>
    <field column="SALES" name="Sales"/>
  </hidden_info>
  <rule>
    <features style="M.CIRCLE">(city=:1 and sales>:2)</features>
    <label column="NAME" style="T.TEXT"> 1 </label>
  </rule>
</styling_rules>

In Example 8-7, the binding variable :1 specifies the name of the city in which the qualifying features must be located, and the binding variable :2 specifies the minimum sales volume of the qualifying features. (That is, only customers in a specified city and with sales above a certain minimum will have store markers displayed.) The values of these two binding variables are not fixed when the theme is defined; instead, they are provided in the requests that the client sends to the server.

8.3.1.3 Dynamic JDBC Query Theme-Based FOI Layers

When the client requests FOI data using a dynamic JDBC theme-based FOI request, it must specify the complete definition of the JDBC theme. The theme definition must specify the rendering style and the SQL query that is to be used to query FOI data, including all geometry and non-geometry attributes.

Example 8-8 shows some JavaScript client code to create an FOI layer that displays a buffer around each customer location.

Example 8-8 Theme for Dynamic JDBC Query

var theme = '<themes><theme name="JDBC_THEME" >' +
   '<jdbc_query asis="true" spatial_column="location" 
        jdbc_srid="8307" render_style="C.RED" 
        datasource="mvdemo">' + 
   'select sdo_geom.sdo_buffer(A.location,1,0.005,'+
   '\'unit=mile arc_tolerance=0.005\') location '+
   ' from customers A' +
   '</jdbc_query></theme></themes>' ;      
buffertheme = new MVThemeBasedFOI('buffertheme',theme);

8.3.2 User-Defined FOI Requests

A user-defined FOI is a feature defined on the client side. Unlike the theme-based FOI layer, which is rendered as a collection of features, the user-defined FOI is requested and rendered on an individual basis.

All attributes of the user-defined FOI, including the geometry representation and rendering style, must be provided by the application. The JavaScript map client sends the request, with the geometry representation and rendering style information, to the FOI server. The FOI server renders the FOI image and returns it to the client. The rendering style must be predefined in the USER_SDO_STYLES view.

8.4 Oracle Maps JavaScript API

The Oracle Maps JavaScript client is a browser-based map visualization engine that works on top of the map cache server and the FOI server. It implements the following functions:

To access these functions, use the JavaScript API, which consists of several JavaScript classes, including the following:

MVMapView is the main entry class for all map operations inside the Web browser. MVMapView and the other classes provide all essential interfaces for adding logic to your Web mapping applications. These logical operations can include the following:

For detailed information about all classes in the Oracle Maps JavaScript API, see the Javadoc-style reference documentation, which is included with MapViewer and is available at the following location:

http://host:port/mapviewer/fsmc/apidoc

8.5 Developing Oracle Maps Applications

If you have all your map data stored in an Oracle database and have MapViewer deployed in Oracle Application Server, you can develop a Web-based mapping application using Oracle Maps by following the instructions in this section.

8.5.1 Creating One or More Map Cache Instances

An Oracle Maps application usually displays at least one base map layer as the static map background. You must create a map cache instance for each base map. For example, for the sample application described in Section 8.1.2, you must create a map cache instance for the base map that displays oceans, county boundaries, cities and highways.

Before you can create a map cache instance, you must ensure that the map source from which the map tiles images are to be rendered is ready. If the map tile images are rendered based on map data stored in the database, you must create a MapViewer base map that consists of a set of predefined themes. (You can create the base map using the Map Builder tool, which is described in Chapter 9.) If the map tiles images are rendered by an external map provider, you must write a map source adapter that can fetch map images from the external server using the tile image definition specified by the map cache server.

When the map source is ready, you can create the map cache instance using the MapViewer administration page, as described in Section 1.5.3. When you create the map cache instance, you must provide proper coordinate system definition, map source definition (internal or external), and zoom level definition (number of zoom levels and map scales).

After you create the map cache instance, you can test it by using a JavaServer Page (JSP) demo application shipped with MapViewer. The JSP demo application can be accessed at http://host:port/mapviewer/fsmc/omaps.jsp. Based on your input, this application can display maps served by any map cache instance defined with the MapViewer instance.

If your application needs to display more than one base map layer, you must create a map cache instances for each base map.

8.5.2 Defining FOI Metadata

If your application needs to display dynamic features based on database query results as theme-based FOI layers, you must create a predefined MapViewer theme for each theme-based FOI layer. If your application needs to display individual dynamic features as user-defined FOIs, you must define the rendering style or styles used by the FOI server to render the FOI images. You can use the Map Builder tool (described in Chapter 9) to create predefined themes and rendering styles.

8.5.3 Creating the Client Application

Oracle Maps client applications running inside Web browsers are pure HTML and JavaScript pages that do not require any plug-ins. Therefore, you can build the application using any Web technology that delivers content as pure HTM. Such technologies include JavaServer Pages, Java Servlets, ASP, and .NET C#. This section discusses client application development only in pure HTML format, but you can easily apply this information to other Web technologies.

As shown in Example 8-1 in Section 8.1.2, the source code for an Oracle Maps application is typically packaged in an HTML page, which consists of the following parts:

  • A <script> element that loads the Oracle Maps client library into the browser JavaScript engine. In Example 8-1, this element is:

    <script language="Javascript" src="jslib/loadscript.js"></script>
    
    
  • An HTML DIV element that is used as the map container in the Web page. The size and positioning of the DIV element can be customized to suit your needs. In Example 8-1, this element is:

    <div id="map" style="left:10; top:60;width: 600px; height: 500px"></div>
    
    
  • JavaScript code that creates and initializes the map client instance. It creates the map client instance, sets up the initial map content (base map, FOI layers, and so on), sets the initial map center and zoom level, implements application-specific logic, and displays the map, sets up initial map contents (base map, FOI layers, and so on), and implements other application-specific logic.

    This code should be packaged inside a JavaScript function, which is executed when the HTML page is loaded from the server to the client Web browser. In Example 8-1, this function is named on_load_mapview:

    function on_load_mapview() 
    {  
      var baseURL  = "http://"+document.location.host+"/mapviewer";
      // Create an MVMapView instance to display the map
      var mapview = new MVMapView(document.getElementById("map"), baseURL);
      // Add a base map layer as background.
      mapview.addBaseMapLayer(new MVBaseMap("mvdemo.demo_map"));   
      // Add a theme-based FOI layer to display customers on the map
      var themebasedfoi = new MVThemeBasedFOI('themebasedfoi1','mvdemo.customers');
      themebasedfoi.setBringToTopOnMouseOver(true);
      mapview.addThemeBasedFOI(themebasedfoi);
      // Set the initial map center and zoom level
      mapview.setCenter(MVSdoGeometry.createPoint(-122.45,37.7706,8307));   
      mapview.setZoomLevel(4);    
      // Add a navigation panel on the right side of the map
      mapview.addNavigationPanel('east');
      // Add a scale bar
      mapview.addScaleBar();
      // Display the map.
      mapview.display();
    }
    
    

    This function is specified in the onload attribute of the <body> element, so that it is executed after the Web page is loaded. In Example 8-1, this code is as follows:

    <body onload= JavaScript:on_load_mapview() >
    
    
  • Additional HTML elements and JavaScript code implement other application-specific user interfaces and control logic. In Example 8-1 in Section 8.1.2, a JavaScript function setLayerVisible is implemented to show or hide the theme-based FOI layer when the user checks or unchecks the Show customers check box. The setLayerVisible function is coded as follows:

    function setLayerVisible(checkBox)
    {
            // Show the theme-based FOI layer if the check box is checked
            // and hide the theme-based FOI layer otherwise.
      if(checkBox.checked)
        themebasedfoi.setVisible(true) ;
      else
        themebasedfoi.setVisible(false);
    }
    
    

    This function is specified in the onclick attribute of the <INPUT> element that defines the check box, so that it is executed whenever the user clicks on the check box. In Example 8-1, this code is as follows:

    <INPUT TYPE="checkbox" onclick="setLayerVisible(this)" checked/>Show customers