[GIS] OpenLayers: cache WFS Request for Vector Layer

cacheopenlayers-2requestwfs

In our mobile application, we'd like to use the map offline.

Actually, we don't care about tiles, but we want the user to be able to see some Vector layers.
Here is a piece of code:

            layer = new OpenLayers.Layer.Vector("Block", {
                strategies: [new OpenLayers.Strategy.BBOX()],
                filter: VMMS.GIS.GetBlockFilter(i),
                protocol: new OpenLayers.Protocol.WFS({
                    url: self.urlProxyGeoserver,
                    version: "1.1.0",
                    featureType: "block",
                    featureNS: self.urlGeoserver + self.dataStore,
                    featurePrefix: self.dataStore,
                    srsName: "EPSG:900913",
                    geometryName: "block_geom",
                    schema: self.urlGeoserver + "wfs/DescribeFeatureType?version=1.1.0&typename=" + self.dataStore + ":block"

                }),
                projection: "EPSG:900913",
                styleMap : self.StyleBlockWithOpacity
            });

I would like to be able to load this layer before to be offline, then use it.
I tried to do it, and cache it with localstorage (HTML5), but some problems occurs because of javascript cyclic object.

I could make the request (with url parameter) with my own API, and then cache the response. But I have the feeling that we have to use OpenLayers API.

Otherwise, do you have any idea?

On google, I have only seen solution to cache tiles, but not about my problem.
I'm kind of newbie to Openlayers, so I might have miss something. In that case, I would be happy to know what 🙂

Thanks

Edit:
By the way, I tried the recommandation there: WFS Caching / Back button
But it's not working (or doesn't match with my needs for some)

Best Answer

One option is to store the features in the mobile local storage like a sqlite database, you can even store it in a html5 web sql database. When it's offline you can create the layer from stored feature.

Edit:

Following is the code to save the features (in geojson format) to local storage

var features = ...; // This is the features you will store in local storage

var geojsonParser = new OpenLayers.Format.GeoJSON();

var feature_geojson_list = [];
for (var i=0; i<features.length; i++) {
    var feature_geojson = geojsonParser.write(features[i]);
    feature_geojson_list.push(feature_geojson);
}

//save feature_geojson_list to local storage
...

Following is how you create feature from the geojson objects (when it's offline):

var feature_geojson_list = ... // read feature geojson list from local storage

var geojsonParser = new OpenLayers.Fomrat.GeoJSON();

var features = [];

for (var i=0; i<feature_geojson_list.length; i++) {
    var feature = geojsonParser.read(feature_geojson_list[i], "Feature");
    features.push(feature);
}

// now add features to your layer
...

More edits: So in your map page, there will be some kind of connection check, and you get the features from different sources depend on whether it's online or offline.


if (**api_meothod_return_mobile_is_online**) {
    // when it's on line you get the layer from server
    var layer = new OpenLayers.Layer.Vector("Block", {
                strategies: [new OpenLayers.Strategy.BBOX()],
                filter: VMMS.GIS.GetBlockFilter(i),
                protocol: new OpenLayers.Protocol.WFS({
                    url: self.urlProxyGeoserver,
                    version: "1.1.0",
                    featureType: "block",
                    featureNS: self.urlGeoserver + self.dataStore,
                    featurePrefix: self.dataStore,
                    srsName: "EPSG:900913",
                    geometryName: "block_geom",
                    schema: self.urlGeoserver + "wfs/DescribeFeatureType?version=1.1.0&typename=" + self.dataStore + ":block"

                }),
                projection: "EPSG:900913",
                styleMap : self.StyleBlockWithOpacity
            });

     // some other code 
     map.addLayer(layer);
     ... 

     //after you get the features from server, you need to store them to local storage. 
     //But make sure all features get loaded before storing the features, 
     //so you probably need to listen on layer's 'loadend' event.

     //**Additional comments from new comments: if you only cache the data by
     //clicking some button, this is not the right code. Make it listen on
     //the button clicking event. But also make sure all the wfs features get loaded
     //before you clicking the button.
     layer.events.on('loadend', layer, function(event) {
         //here cache all layer features to local storage
         var features = layer.features;
         var geojsonParser = new OpenLayers.Format.GeoJSON();
         ... // the same code above.
     }); 
}
else {
    // when it's offline, you get the layer from local storage
    // note you just need to create a normal empty vector layer, but with same projection and stylemap
    var layer = new OpenLayers.Layer.Vector("Block", {
         projection: "EPSG:900913",
         styleMap: self.StyleBlockWithOpacity
    });

    //some other code
    map.addLayer(layer);
    ...

    // read features from local storage
    var feature_geojson_list = ... // if you don't find any feature in local storage, that means the app never get online, process the application properly in such case.
    var geojsonParser = new OpenLayers.Fomrat.GeoJSON();

    ... // the same code above

    // after get the features, add it to the layer
    layer.addFeatures(features);
}

The above code is quite primitive, you need to modify it according to your own application.