| Home | Products | Issue Tracker | Service Providers | FAQ | Twitter | Download

# Sample: WFS-T with TinyOWS and OpenLayers

0. Install PostGIS and TinyOWS (TinyOWS Installation)

1. Within PostGIS, create a spatial database called ‘tinyows’

    createdb -U postgres tinyows
    psql -U postgres -d tinyows < `pg_config --sharedir`/contrib/postgis-2.0/postgis.sql
    psql -U postgres -d tinyows < `pg_config --sharedir`/contrib/postgis-2.0/spatial_ref_sys.sql

2. Import Frida data (we will use the parks layer) into your PostGIS database

    wget ftp://ftp.intevation.de/freegis/frida/frida-1.0.1-shp.tar.gz
    tar xvzf frida-1.0.1-shp.tar.gz
    cd frida-1.0.1-shp
    shp2pgsql -g geom -s 31467 -W LATIN1 -I gruenflaechen.shp frida | psql -U postgres -d tinyows

3. Configure TinyOWS by editing /usr/local/tinyows/config.xml

    <tinyows online_resource="http://127.0.0.1/cgi-bin/tinyows"
             schema_dir="/usr/local/share/tinyows/schema/">

    <pg host="127.0.0.1" user="postgres" password="postgres" dbname="tinyows" port="5432"/>

    <metadata name="TinyOWS Server"
              title="TinyOWS Server - WFS-T Frida Service" />

    <contact name="TinyOWS Server"
             site="http://www.mapserver.org/tinyows/"
             email="tinyows-users@lists.maptools.org" />

    <layer retrievable="1"
           writable="1"
           ns_prefix="tows"
           ns_uri="http://www.mapserver.org/tinyows/"
           name="frida"
           title="Frida Parks" />

    </tinyows>

4. Test your installations of TinyOWS and PostGIS

    ./YOUR_CGI-BIN_PATH/tinyows --check
    TinyOWS version:   1.1.0
    FCGI support:      Yes
    Config File Path:  /etc/tinyows.xml (TinyOWS XML)
    PostGIS Version:   2.0.1
    PostGIS dsn:       host=127.0.0.1 user=postgres password=postgres dbname=tinyows port=5432
    Output Encoding:   UTF-8
    Database Encoding: UTF8
    Schema dir:        /usr/local/share/tinyows/schema/
    Display bbox:      Yes
    Estimated extent:  No
    Check schema:      Yes
    Check valid geoms: Yes
    Available layers:
     - public.frida (31467) -> tows:frida [RW]

5. Install OpenLayers

    wget http://openlayers.org/download/OpenLayers-2.12.tar.gz
    tar xvzf OpenLayers-2.12.tar.gz
    sudo mv OpenLayers-2.12  /YOUR/SERVER/HTDOCS/

6. Install the OpenLayers proxy (you need the Python interpreter to make it work)

    sudo cp OpenLayers-2.12/examples/proxy.cgi  /YOUR/SERVER/CGI-BIN/

7. Add your server IP to proxy allowedHosts in (/YOUR/SERVER/CGI-BIN/proxy.cgi)

    allowedHosts = ['127.0.0.1', 'www.openlayers.org', 'openlayers.org', ... ]

8. Create a new file at OpenLayers-2.12/examples/tinyows.html

    <html>
    <head>
      <link rel="stylesheet" href="../theme/default/style.css" type="text/css" />
      <link rel="stylesheet" href="style.css" type="text/css" />
      <script src="../lib/OpenLayers.js"></script>
      <style>
          #map {
              width: 800px;
              height: 500px;
              float: left;
              border: 1px solid #ccc;
          }
          #message {
              position: relative;
              left: 5px;
          }
          #docs {
              float: left;
          }
          .customEditingToolbar {
              float: right;
              right: 0px;
              height: 30px;
              width: 200px;
          }
          .customEditingToolbar div {
              float: right;
              margin: 5px;
              width: 24px;
              height: 24px;
          }
          .olControlNavigationItemActive {
              background-image: url("../theme/default/img/editing_tool_bar.png");
              background-repeat: no-repeat;
              background-position: -103px -23px;
          }
          .olControlNavigationItemInactive {
              background-image: url("../theme/default/img/editing_tool_bar.png");
              background-repeat: no-repeat;
              background-position: -103px -0px;
          }
          .olControlDrawFeaturePolygonItemInactive {
              background-image: url("../theme/default/img/editing_tool_bar.png");
              background-repeat: no-repeat;
              background-position: -26px 0px;
          }
          .olControlDrawFeaturePolygonItemActive {
              background-image: url("../theme/default/img/editing_tool_bar.png");
              background-repeat: no-repeat;
              background-position: -26px -23px ;
          }
          .olControlModifyFeatureItemActive {
              background-image: url(../theme/default/img/move_feature_on.png);
              background-repeat: no-repeat;
              background-position: 0px 1px;
          }
          .olControlModifyFeatureItemInactive {
              background-image: url(../theme/default/img/move_feature_off.png);
              background-repeat: no-repeat;
              background-position: 0px 1px;
          }
          .olControlDeleteFeatureItemActive {
              background-image: url(../theme/default/img/remove_point_on.png);
              background-repeat: no-repeat;
              background-position: 0px 1px;
          }
          .olControlDeleteFeatureItemInactive {
              background-image: url(../theme/default/img/remove_point_off.png);
              background-repeat: no-repeat;
              background-position: 0px 1px;
          }
      </style>
      <script src="tinyows.js"></script>
      </head>
      <body onload="init()">
          <h1 id="title">WFS Transaction Example, (TinyOWS ans OpenLayers)</h1>
          <div id="tags"></div>
          <p id="shortdesc">
              Shows the use of the WFS Transactions (WFS-T).
              Parks of Osnabruck (Frida).
          <br />
              Base layers is OpenStreetMap from Omniscale WMS Server.
          </p>
          <div id="map"></div>

          <div id="message"></div>
          <div id="docs">
              <p>
                  The WFS protocol allows for creation of new features and
                  reading, updating, or deleting of existing features.
              </p>
              <p>
                  Use the tools to create, modify, and delete (in order from left
                  to right) features. Use the save tool (picture of a disk) to
                  save your changes. Use the navigation tool (hand) to stop
                  editing and use the mouse for map navigation.
              </p>
              <p>
                  See the <a href="tinyows.js" target="_blank">
                  wfs-protocol-transactions.js source</a> to see how this is done.
              </p>
          </div>
      </body>
    </html>

9. Create a new file at OpenLayers-2.12/examples/tinyows.js (and replace all 127.0.0.1 addresses by your IP server if necessary)

    var map, wfs;
    OpenLayers.ProxyHost = "/cgi-bin/proxy.cgi?url=";
    var DeleteFeature = OpenLayers.Class(OpenLayers.Control, {
      initialize: function(layer, options) {
          OpenLayers.Control.prototype.initialize.apply(this, [options]);
          this.layer = layer;
          this.handler = new OpenLayers.Handler.Feature(
              this, layer, {click: this.clickFeature}
          );
      },
      clickFeature: function(feature) {
          // if feature doesn't have a fid, destroy it
          if(feature.fid == undefined) {
              this.layer.destroyFeatures([feature]);
          } else {
              feature.state = OpenLayers.State.DELETE;
              this.layer.events.triggerEvent("afterfeaturemodified",
                                             {feature: feature});
              feature.renderIntent = "select";
              this.layer.drawFeature(feature);
          }
      },
      setMap: function(map) {
          this.handler.setMap(map);
          OpenLayers.Control.prototype.setMap.apply(this, arguments);
      },
      CLASS_NAME: "OpenLayers.Control.DeleteFeature"
    });
    function showMsg(szMessage) {
      document.getElementById("message").innerHTML = szMessage;
      setTimeout(
          "document.getElementById('message').innerHTML = ''",2000);
    }
    function showSuccessMsg(){
      showMsg("Transaction successfully completed");
    };
    function showFailureMsg(){
      showMsg("An error occurred while operating the transaction");
    };
    function init() {
      map = new OpenLayers.Map('map', {
          projection: new OpenLayers.Projection("EPSG:31467"),
          units: "m",
          maxResolution: "auto",
          maxExtent: new OpenLayers.Bounds(3427000,5788000,3444000,5800000),
          controls: [
              new OpenLayers.Control.PanZoom()
          ]
      });
      var osm = new OpenLayers.Layer.WMS(
          "OSM by Omniscale WMS",
          "http://osm.omniscale.net/proxy/service",
          {layers: 'osm', format: 'image/jpeg'},
          {projection:"EPSG:31467",  units: "m", maxResolution: "auto", maxExtent: new OpenLayers.Bounds(3427000,5788000,3444000,5800000)}
      );
      var saveStrategy = new OpenLayers.Strategy.Save();
      saveStrategy.events.register("success", '', showSuccessMsg);
      saveStrategy.events.register("fail", '', showFailureMsg);
      wfs = new OpenLayers.Layer.Vector("Editable Features", {
          strategies: [new OpenLayers.Strategy.BBOX(), saveStrategy],
          projection: new OpenLayers.Projection("EPSG:31467"),
          protocol: new OpenLayers.Protocol.WFS({
              version: "1.1.0",
              srsName: "EPSG:31467",
              url: "http://127.0.0.1/cgi-bin/tinyows",
              featureNS :  "http://www.mapserver.org/tinyows/",
              featureType: "frida",
              geometryName: "geom",
              schema: "http://127.0.0.1/cgi-bin/tinyows?service=wfs&request=DescribeFeatureType&version=1.1.0&typename=tows:frida"
          })
      });
      map.addLayers([osm, wfs]);
      var panel = new OpenLayers.Control.Panel(
          {'displayClass': 'customEditingToolbar'}
      );
      var navigate = new OpenLayers.Control.Navigation({
          title: "Pan Map"
      });
      var draw = new OpenLayers.Control.DrawFeature(
          wfs, OpenLayers.Handler.Polygon,
          {
              title: "Draw Feature",
              displayClass: "olControlDrawFeaturePolygon",
              multi: true
          }
      );
      var edit = new OpenLayers.Control.ModifyFeature(wfs, {
          title: "Modify Feature",
          displayClass: "olControlModifyFeature"
      });
      var del = new DeleteFeature(wfs, {title: "Delete Feature"});
      var save = new OpenLayers.Control.Button({
          title: "Save Changes",
          trigger: function() {
              if(edit.feature) {
                  edit.selectControl.unselectAll();
              }
              saveStrategy.save();
          },
          displayClass: "olControlSaveFeatures"
      });
      panel.addControls([navigate, save, del, edit, draw]);
      panel.defaultControl = navigate;
      map.addControl(panel);
      map.zoomToMaxExtent();
    }