Table Of Contents

Previous topic

Installing and Running MapFishSample

Next topic

Securing MapFishSample

This Page

Studying MapFishSample

In the previous module we have seen how to build and deploy the MapFishSample application. More generally we have seen how to use Buildout to build and deploy MapFish applications.

In this module we will study MapFishSample. We’ll see how MapFishSample is structured, and how its connections to external components, such as MapServer and MapFish Print, are organized.

General Structure

MapFishSample is a MapFish application, i.e. an application created with the mapfish template, it is therefore structured like any MapFish application.

At the root of MapFishSample we find these files and directories:

apache
This directory includes the Apache configuration for the application and external components the application relies on (MapServer, MapFish Print). The content of this directory can be added to the Apache configuration using Apache’s Include directives.
buildout
This directory includes the Python environment created by Buildout. This is where Buildout adds the python interpreter, and installs the application and its dependencies. It is filled when the Buildout process is launched the first time.
buildout_*.cfg
These are Buildout configuration files. buildout.cfg is the main configuration file, it includes the common part. The other files extend buildout.cfg, to deal with specific execution environments.
mapfishsample
This directory includes the actual code of the MapFishSample application.
development.ini and production.ini

These files include the configuration of MapFishSample itself. development.ini is to be used with the Paste HTTP Server during development, while production.ini is to be used with modwsgi, in production.

Both files are generated by Buildout (the template part) from their .ini counterpart. They are generated at deployment time because they include parameters, e.g. the database connection parameters, that are specific to the execution environment.

jsbuild
This directory includes the build profile for the JavaScript code. The path to this build profile is given to the JSTools:buildjs Buildout recipe, through the config variable in the [jsbuild] section of buildout.cfg.
mapserver
This directory includes the MapServer configuration, that is a mapfile, fonts and symbols.
print

This directory includes the MapFish Print configuration, i.e. the YAML config file. It could also include images, and PDF files, that are to be bundled in the MapFish Print webapp.

The c2c.recipe.jarfile is responsible for bundling the YAML file and the resource files into the MapFish Print webapp.

tilecache
This directory includes the TileCache configuration. MapFishSample does not actually use TileCache, so this directory currently serves no purpose in the case of MapFishSample.

Task #1

Open apache/mapserver.conf.in and apache/mapserver.conf, and note how the mapfile is made available to MapServer.

Source Code Organization

The actual code of MapFishSample is located in the mapfishsample directory. This directory includes several sub-directories, the most important ones are:

controllers

This directory includes the controllers of the application. Controllers are written in Python. They contain the code that receive HTTP requests, take appropriate action, and send HTTP responses.

The two main controllers in MapFishSample are entry.py and pois.py.

entry.py defines the entry point of the application, it receives the very first request when the browser loads http://mapfish/.

pois.py implements the MapFish web service for the poi_osm table. This is the web service used for the Query and Editing functionalities.

templates

This directory includes HTTP templates (as a matter of fact it also includes JavaScript templates). The Mako template engine is used for the processing of templates.

The main template is index.html, which is the HTML page displayed when http://mapfish/ is opened in the browser. This template is rendered when the index action of the entry.py controller is invoked.

model
This directory includes the database model of MapFishSample. The main file of this directory is __init__.py, and this is where the model of the poi_osm table is defined.
public

This directly includes the static content of MapFishSample, i.e. the JavaScript code, CSS, images, etc.

The JavaScript code of the application, which controls the browser UI, is located in the app/lib/App directory.

The JavaScript toolkits - OpenLayers, ExtJS, and GeoExt - are located in the lib directory.

Task #2

Open http://mapfish/?debug=true in the browser. Open FireBug with F12 and go to the Net tab. Reload the page. The loading of the page should take longer than previously. And more JavaScript files should be downloaded. Setting debug in the URL indeed results in individually loading every JavaScript file composing the application. When debug is not set the app.js built file is loaded.

Open mapfishsample/controllers/entry.py and mapfishample/templates/index.html in the editor, and understand how this mechanism works (Hint: look up c.debug).

Modify The Client Code

As mentioned in the previous section the application-specific code is located in the mapfishsample/public/app/lib/App directory.

The entry point of the JavaScript application is defined in the main.js file. This file defines the function called when the HTML page is loaded in the browser. This function starts by setting global variables, and then creates the map in the page.

The map-related code is in the Map.js file. The App.Map function defined in this file basically creates the map, the layers, and the toolbar that contains the buttons to enable/disable the Query, Editing, Search and Printing functionalities. The toolbar-related code is itself located in the App.Tools function of the Tools.js file.

Task #3

Open Tools.js in the editor. Take a look at the code, paying attention to the functions belonging to the App namespace, and attempt to open the relevant JavaScript files as you go through the code.

Hint: also pay attention to the @include directives at the heads of files.

Task #4

In this task you’re going to modify the JavaScript code of the application.

Start by opening http://mapfish/ in the browser. Active the Search functionality, select “Fastfood” in the “Type” select, and hit “Search”. In the popup use the left and right arrows to browse through the results, and observe that the map isn’t recentered when a result is selected. You’re going to change that!

Open Search.js in the editor, and look up the featureselected listener. At the end of the function add the following code:

var ll = new OpenLayers.LonLat(
    feature.geometry.x, feature.geometry.y);
mapPanel.map.setCenter(ll);

Reload the page in the browser, and check if the behavior has changed. It shouldn’t have, because the JavaScript hasn’t been rebuilt. If you open http://mapfish/?debug=true you should get the expected behavior though.

To build the JavaScript code again, execute this command line at the root of MapFishSample:

$ ./buildout/bin/buildout -c buildout_mine.cfg install jsbuild

The install argument allows targeting a specific part of the Buildout configuration. In that case only the jsbuild part is executed.

Now http://mapfish/ should behave as expected. Verify that.

MapServer

MapFishSample relies on MapServer for the display of POIs on the map. WMS is used for that (WMS request example). MapServer is an external component of MapFishSample, it needs to be installed on the system for MapFishSample to work properly.

Linking MapFishSample and MapServer together is done through multiple things:

  1. The mapserver directory includes a MapServer mapfile. This mapfile represents the MapFishSample-specific MapServer configuration.
  2. The apache directory includes an Apache configuration file for MapServer: mapserver.conf. This configuration file defines the URL to access MapServer, and provides MapServer with the path to the mapfile (through the MS_MAPFILE environment variable).
  3. The URL to MapServer is made available to the JavaScript code through the App.mapservURL JavaScript variable. This variable is set in the mapfishsample/templates/global.js file, which is generated by Buildout from mapfishsample/templates/global.js.in and variables defined in the Buildout configuration.

Task #5

In this task you’re going to modify the mapfile and see what must be done to make your modification effective.

Edit mapserver/mapfishsample.map.in, look up the sustenance layer (this is the POI layer), and change the value of its LABELITEM property from "name" to "type".

You have modified a .in file so the template part of Buildout must be executed again:

$ ./buildout/bin/buildout -c buildout_mine.cfg install template

You may have noticed when looking at apache/mapserver.conf that the FastCGI interface is used for MapServer. FastCGI is preferred to CGI because it leads to better performance, especially when MapServer reads data from PostgreSQL/PostGIS. One consequence of that is that Apache needs to be reloaded for changes to the mapfile to be effective:

$ sudo /etc/init.d/apache reload

Reload http://mapfish/ in the browser. The label under a POI symbol should now be the type of the POI, instead of its name. Verify that.

Print

MapFishSample relies on MapFish Print for the Print functionality. Here again MapFish Print is an external component of MapFishSample.

In contrast to MapServer, MapFish Print is downloaded and installed by MapFishSample’s Buildout process. But MapFishSample requires that Apache Tomcat is up and running on the system.

The following describes how MapFishSample and MapFish Print are linked together:

  1. The print directory includes the YAML configuration file, config.yaml, for MapFish Print.
  2. The [print] Buildout part downloads the MapFish Print war file into the print directory.
  3. The [deploy-print] unpacks this war file, re-pack it together with the MapFish Print configuration file (config.yaml), and deploys it into Tomcat. The variable output of the [deploy-print] section in buildout.cfg specifies where the Tomcat webapps directory is.
  4. The apache directory includes an Apache configuration for MapFish Print: tomcat-print.conf. This file sets up a proxy to the MapFish Print webapp executed by Tomcat.

At any time one can use the following command to redeploy the MapFish Print webapp into Tomcat:

$ ./buildout/bin/buildout -c buildout_mine.cfg install deploy-print

Task #6

In a similar way to Task #5 you’re going to change the MapFish Print configuration in this task, and make your change effective.

Edit print/config.yaml.in and make some changes of your choice (change the map size for example).

Now re-generate print/config.yaml from print/config.yaml.in, and re-build and re-deploy the MapFish Print webapp using:

$ /buildout/bin/buildout -c buildout_mine.cfg install template deploy-print

Reload http://mapfish/ in the browser, print a map, and check that you get what you expect.

TileCache

In its current form MapFishSample doesn’t use TileCache (mostly because MapFishSample uses an OSM layer as the map baselayer). But TileCache is set up in MapFishSample, so using TileCache in the future will be straightfoward.

First of all TileCache is configured as a dependency of MapFishSample. Dependencies are expressed through the install_requires variable in setup.py. Because of this dependency TileCache was installed in the Python environment when Buildout was run for the first time.

MapFishSample also includes a controller for TileCache. See mapfishsample/controller/tilecache.py. This controller is a wrapper for TileCache. Embedding TileCache within the application greatly simplifies the installation and deployment of TileCache. It also makes it possible to secure TileCache web services using Pylons-compatible security frameworks such as repoze.who. We will talk about again that in the next module.

Task #7

In this task you’re going to modify MapFishSample to go through TileCache instead of accessing MapServer directly.

  1. The first thing to do is configure TileCache, i.e. define the TileCache layer and its connection to MapServer.

    Edit tilecache/tilecache.cfg.in and replace its content by this:

    [cache]
    type = Disk
    base = /var/sig/tilecache/mapfishsample-${instanceid}_tilecache
    
    [DEFAULT]
    type = WMSLayer
    url = ${vars:mapserv_url}
    srs = EPSG:900913
    maxResolution = 156543.0339
    levels = 18
    bbox = -20037508.339200001,-20037508.339200001,20037508.339200001,20037508.339200001
    extension = png
    
    [sustenance]

    With this content a TileCache layer named sustenance is defined. This layer is mapped to the MapServer layer of the same name.

  2. To generate tilecache/tilecache.cfg execute the [template] Buildout part:

    $ ./buildout/bin/buildout -c buildout_mine.cfg install template
  3. You now need to change the JavaScript code so it accesses TileCache instead of MapServer for the POI WMS layer. For that edit mapfishsample/public/app/lib/App/Map.js, look up the POIS layer, change its url from App.mapservURL to App.tilecacheURL, and its singleTile option from true to false. The definition of the WMS layer should now look like this:

    poisLayer = new OpenLayers.Layer.WMS(
        'POIS',
        App.tilecacheURL,
        {
            layers: ['sustenance'],
            transparent: true
        },
        {
            singleTile: false
        }
    );
  4. Build the JavaScript code again, by executing the [jsbuild] Buildout part:

    $ ./buildout/bin/buildout -c buildout_mine.cfg install jsbuild
  5. Reload http://mapfish/ in the browser. The POIs layer should still be displayed.

    If you create a new POI using the Editing functionalilty you’ll observe that the new object won’t appear in the WMS layer. This is a cached layer!

This section has shown how MapFishSample, and any MapFish application, can embed TileCache. It is interesting to note that any MapFish application can wrap any application implementing the WSGI interface. For example, embedding MapProxy, an alternative to TileCache, should be equally feasible.