OpenLayers 3.16 – Three flavours of Geoserver WFS as ol.layer.Vector

Today I want to recap on the different ways of adding a vector layer from a Geoserver WFS. I used OL 3.5 when I published this post in May 2015. Since then I have switched to OL 3.16 and decided to update this post rather than to write a new post. There is really no reason not to be working with the latest version of OpenLayers. If you are familiar with WFS vector sources in OpenLayers 3.x or if you used my previous code snippets then please review the update notes. There have been a few significant changes between OL 3.5 and OL 3.16.

The examples are based on the vector-wfs example from the OpenLayers page.

We create a vector layer with a WFS source like so:

var layerWFS = new ol.layer.Vector({
  source: new ol.source.Vector({
    loader: function(extent) {
      $.ajax('http://demo.opengeo.org/geoserver/wfs', {
        type: 'GET',
        data: {
          service: 'WFS',
          version: '1.1.0',
          request: 'GetFeature',
          typename: 'water_areas',
          srsname: 'EPSG:3857',
          bbox: extent.join(',') + ',EPSG:3857'
        }
      }).done(function(response) {
        layerWFS
        .getSource()
        .addFeatures(new ol.format.WFS()
          .readFeatures(response));
      });
    },
    strategy: ol.loadingstrategy.bbox,
    projection: 'EPSG:3857'
  })
});

We use a bbox loading strategy and use the extent in the loader function for the WFS source.

By default the WFS request will return XML from Geoserver. Inside the .done() function we define WFS format object which will be used to read the features from the WFS response and add these to the source.

Here is a working JSFiddle for this code.

As an alternative to the WFS format we can directly request GeoJSON from GeoServer. GeoJSON will be more compact and easier to parse.

var layerWFS = new ol.layer.Vector({
    source: new ol.source.Vector({
        loader: function (extent) {
            $.ajax('http://demo.opengeo.org/geoserver/wfs', {
                type: 'GET',
                data: {
                    service: 'WFS',
                    version: '1.1.0',
                    request: 'GetFeature',
                    typename: 'water_areas',
                    srsname: 'EPSG:3857',
                    outputFormat: 'application/json',
                    bbox: extent.join(',') + ',EPSG:3857'
                }
            }).done(function (response) {
                layerWFS
                .getSource()
                .addFeatures(new ol.format.GeoJSON()
                  .readFeatures(response));
            });
        },
        strategy: ol.loadingstrategy.bbox,
        projection: 'EPSG:3857'
    })
});

We define the outputFormat as ‘application/json’ inside the AJAX call.

In order to read the features from the GeoJSON response we use a GeoJSON format object inside the .done() function.

Here is a working JSFiddle.

An alternative to the JSON format is the JSONP format which allows us to receive data from Geoserver without changing the CORS access on the webserver. JSONP is by default disabled and must be enabled in Geoserver.

The AJAX call must configured as shown below for the callback with padded JSON.

var layerWFS = new ol.layer.Vector({
    source: new ol.source.Vector({
        loader: function (extent) {
            $.ajax('http://demo.opengeo.org/geoserver/wfs', {
                type: 'GET',
                data: {
                    service: 'WFS',
                    version: '1.1.0',
                    request: 'GetFeature',
                    typename: 'water_areas',
                    srsname: 'EPSG:3857',
                    outputFormat: 'text/javascript',
                    bbox: extent.join(',') + ',EPSG:3857'
                },
                dataType: 'jsonp',
                jsonpCallback:'callback:loadFeatures',
                jsonp: 'format_options'
            })
        },
        strategy: ol.loadingstrategy.bbox,
        projection: 'EPSG:3857'
    })
});

window.loadFeatures = function (response) {
    layerWFS
    .getSource()
    .addFeatures(new ol.format.GeoJSON().readFeatures(response));
};

We set the output format in the AJAX call to be ‘text/javascript’. We don’t use a .done() function on the AJAX call but define dataType, jsonp, and jsonCallback parameter. The response from the WFS call will be sent to the jsonCallback function. Inside the load features function we use again a GeoJSON format object to read features from the response and add these to the source of the WFS layer.

Here is a working JSFiddle.

If you have problems loading data I recommend to use the Chrome developer tools (F12). A common error is the use of a http source on a https page.

wfs_https_error

Filter for XHR on the network tab of the debug tools to inspect the details of your WFS calls.

wfs_chrome_debug

Please drop me a comment if this helped you, if you have questions or if you can recommend further improvements to these examples.

Next time… WFS-T.

 

 

6 thoughts on “OpenLayers 3.16 – Three flavours of Geoserver WFS as ol.layer.Vector”

  1. The javascript code in the last black box doesn’t match its’ fiddle. It appears to be a duplicate of the previous black box (i.e. the one for json).

  2. Hi,

    Thanks for the awesome tutorial and sample code. I implemented your code in conjunction with one of the Example Code provided by OpenLayers3 and it works perfectly. However, I’m very confused about how to set up the geoserver to work with openlayers.

    This is how it is in my geoserver:
    Workspace namespace URI: http://www.opengeospatial.net/OpenGeoTest
    Storename: Example (Type: PostGIS)
    Layers: wfst_test
    Native & Declared SRS: EPSG:26910

    and I used the following:

    sourceVector = new ol.source.Vector({
    loader: function(extent) {
    $.ajax(‘http://localhost:8080/geoserver/wfs’,{
    type: ‘GET’,
    data: {
    service: ‘WFS’,
    version: ‘1.1.0’,
    request: ‘GetFeature’,
    typename: ‘wfst_test’,
    srsName: ‘EPSG:26910’,
    //cql_filter: “property=’Value'”,
    //cql_filter: “BBOX(geometry,” + extent.join(‘,’) + “)”,
    bbox: extent.join(‘,’) + ‘,EPSG:26910’
    },
    }).done(function(response) {
    formatWFS = new ol.format.WFS(),
    sourceVector.addFeatures(formatWFS.readFeatures(response))
    });
    },
    strategy: ol.loadingstrategy.tile(new ol.tilegrid.createXYZ({
    maxZoom: 19
    })),
    });

    var formatGML = new ol.format.GML({
    featureNS: ‘http://localhost:8080/geoserver/web/OpenGeoTest’,
    featureType: ‘wfst_test’,
    srsName: ‘EPSG:26910’
    });

    $.ajax(‘http://localhost:8080/geoserver/wfs’,{
    type: ‘POST’,
    dataType: ‘xml’,
    processData: false,
    contentType: ‘text/xml’,
    data: str
    }).done();

    I’ve got the response of “Feature type ‘wfst_test’ is not available”. Can you please advise me on what I did wrong?

    Thank you so much!

Leave a Reply

Your email address will not be published. Required fields are marked *