GEOSS Banner

2.2.3 : Simple WFS service


WFS 2.0 defines 4 incremental levels of implementation of WFS: Simple WFS, Basic WFS, Transactional WFS and Locking WFS. This allows implementers to limit themselves to a minimum set of operations.

For the Simple WFS, the server shall implement the following operations: GetCapabilities (all versions), DescribeFeatureType (all versions), ListStoredQueries (WFS 2.0 only), DescribeStoredQueries (WFS 2.0 only), GetFeature (all versions) operation with only the StoredQuery (WFS 2.0 only).

One stored query, which fetches a feature using its id, shall be available although the server may also offer additional stored queries. This stored query shall have the identifier: urn:ogc:def:query:OGC-WFS::GetFeatureById (WFS 2.0 only). In WFS version 1.1, a similar functionality was available using the GetGMLObject operation.

To illustrate how WFS works, we are going to use the Atlas of the Cryosphere as an example: Northern Hemisphere. The Atlas of the Cryosphere uses mapserver software (mapserver.org) over Apache/2.2.3 (Linux/SUSE).

 

2.2.3.1 Describing Your WFS Server: The GetCapabilities operation
2.2.3.1.1 GetCapabilities request
2.2.3.1.2 Capabilities document
2.2.3.2 Describing Your FeatureTypes: The DescribeFeatureType operation
2.2.3.2.1 DescribeFeatureType request
2.2.3.2.2 DescribeFeatureType response: GML application schema
2.2.3.3 Serving a Feature collection: The GetFeature operation
2.2.3.3.1 Implementing GetFeature: Request Parameters
2.2.3.3.2 GetFeature Response. GML data

2.2.3.4 Exceptions

<<Prev T.O.C.  Next>>

2.2.3.1 Describing Your WFS Server: The GetCapabilities operation

2.2.3.1.1 GetCapabilities request

All OWS Common services are self-describing. In the case of WFS this means that you are able to request enough information to the service to know the services details, and you can formulate further requests until you gent the desired data. When you already have the elements you need to get the data, it is then possible to directly request the desired data without a previous information request about the service itself. None the less, it is good that the services are self-describing because it allows the discovery of other services. To explore a WFS service, the only thing you need is the service URL location. There are two possibilities:

• You have a URL that is a GetCapabilites complete request. In this case, you do not need to know anything else. Just using this URL in a web browser will get you the service description. This is what the CSR provides. For example, for the Atlas of the Cryosphere: Northern Hemisphere WFS CSR record (https://geossregistries.info/geosspu...1-e407cb23c7df) you have an entry called "Interface URL" that contains: http://nsidc.org/cgi-bin/atlas_north...etCapabilities

• You only have the URL of the service application: http://nsidc.org/cgi-bin/atlas_north. In this case, you will need to add two mandatory parameters that are the same for all WFS services version 1.1: http://nsidc.org/cgi-bin/atlas_north...etCapabilities
Many WFS implementations support more that one standard version (e.g. you can add "&version=1.0.0" to previous requests to get a WFS 1.0 description). In fact, many current services support WFS 1.0 and 1.1. If you do not request any version in particular, you will then get the latest version available.

2.2.3.1.2 Capabilities document

The response of a correct GetCapabilities request is a capabilities document (also known as "OGC service metadata document"). This is an XML document that has different sections.

image18.png


In this example we are going to examine the Atlas of the Cryosphere: Northern Hemisphere GetCapabilities response document that only uses some of the previous sections:


<?xml version="1.0" encoding="ISO-8859-1"?>

<wfs:WFS_Capabilitiesxmlns:gml="http://www.opengis.net/gml" xmlns:wfs="http://www.opengis.net/wfs" xmlns:ows="http://www.opengis.net/ows" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ogc="http://www.opengis.net/ogc" xmlns="http://www.opengis.net/wfs" version="1.1.0" xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.1.0/wfs.xsd">

<ows:ServiceIdentification>[…]</ows:ServiceIdentification>

<ows:ServiceProvider>[…]</ows:ServiceProvider>

<ows:OperationsMetadata>[…]</ows:OperationsMetadata>

<FeatureTypeList>[…]</FeatureTypeList>

<ogc:Filter_Capabilities>[…]</ogc:Filter_Capabilities>

</wfs:WFS_Capabilities>

The first two sections do not require much explanation because XML element names are quite clear: they provide general information about the service we are going to use such as a title, a description, etc., and information about the people responsible to set it up, as we can see in this XML fragment:


<ows:ServiceIdentification>

<ows:Title>Atlas of the Cryosphere: Northern Hemisphere</ows:Title>

<ows:Abstract>The National Snow and Ice Data Center (NSIDC) Atlas of the Cryosphere is a map server that provides data and information pertinent to the frozen regions of Earth, including monthly climatologies of sea ice extent and concentration, snow cover extent, and snow water equivalent, in addition to glacier outlines, permafrost extent and classification, ice sheet elevation and accumulation, and more. […]

</ows:Abstract>

<ows:Keywords>

<ows:Keyword>Arctic</ows:Keyword>

<ows:Keyword>Cryosphere</ows:Keyword>

[…]

</ows:Keywords>

<ows:ServiceType codeSpace="OGC">OGC WFS</ows:ServiceType>

<ows:ServiceTypeVersion>1.1.0</ows:ServiceTypeVersion>

<ows:Fees>none</ows:Fees>

<ows:AccessConstraints>none</ows:AccessConstraints>

</ows:ServiceIdentification>

<ows:ServiceProvider>

<ows:ProviderName>National Snow and Ice Data Center</ows:ProviderName>

<ows:ProviderSite xlink:type="simple" xlink:href="http://nsidc.org"/>

<ows:ServiceContact>

<ows:IndividualName>NSIDC User Services</ows:IndividualName>

[…]

<ows:PositionName>User Services</ows:PositionName>

<ows:ContactInfo>

[…]

<ows:Address>

[…]

<ows:ElectronicMailAddress>nsidc@nsidc.org

</ows:ElectronicMailAddress>

</ows:Address>

[…]

</ows:ContactInfo>

<ows:Role>resourceProvider</ows:Role>

</ows:ServiceContact>

</ows:ServiceProvider>

Cryosphere is a map server that provides data and information pertinent to the frozen regions of Earth, including monthly climatologies of sea ice extent and concentration, snow cover extent, and snow water equivalent, in addition to glacier outlines, permafrost extent and classification, ice sheet elevation and accumulation, and more. […]




OperationsMetadata section is more interesting to us because it reviles operations that the services support, while allowing us to introduce two further operations: DescribeFeatureType and GetFeature. It also describes the supported values for some parameters like outputFormat.


<ows:OperationsMetadata>

<ows:Operation name="GetCapabilities">[…]</ows:Operation>

<ows:Operation name="DescribeFeatureType">

<ows:DCP>

<ows:HTTP>

<ows:Get xlink:type="simple"
xlink:href
="http://nsidc.org/cgi-bin/atlas_north?"/>

<ows:Post xlink:type="simple"
xlink:href="http://nsidc.org/cgi-bin/atlas_north?"/>

</ows:HTTP>

</ows:DCP>

<ows:Parameter name="outputFormat">

<ows:Value>XMLSCHEMA</ows:Value>

<ows:Value>text/xml; subtype=gml/2.1.2</ows:Value>

<ows:Value>text/xml; subtype=gml/3.1.1</ows:Value>

</ows:Parameter>

</ows:Operation>

<ows:Operation name="GetFeature">

<ows:DCP>

<ows:HTTP>

<ows:Get xlink:type="simple"
xlink:href="http://nsidc.org/cgi-bin/atlas_north?"/>

<ows:Post xlink:type="simple"
xlink:href="http://nsidc.org/cgi-bin/atlas_north?"/>

</ows:HTTP>

</ows:DCP>

<ows:Parameter name="resultType">

<ows:Value>results</ows:Value>

</ows:Parameter>

<ows:Parameter name="outputFormat">

<ows:Value>text/xml; subtype=gml/3.1.1</ows:Value>

</ows:Parameter>

</ows:Operation>

</ows:OperationsMetadata>

WMS services structure the service content into layers that have names. A WFS server does not do that, so, a WFS server can be seen as an enormous mixed collection of features ready to be downloaded. Fortunately, we can filter the information by feature types and, in practice, people are using feature type filtering as a way to separate content in different units (like we do when separating information into different shapefiles. Obviously, it is important to know the name of the contents in order to separate the feature type content. The next section, FeatureTypeList, tells us the type names as well as many details about each feature type. This service has up to 19 feature types, but the following fragment only shows two of them:


<FeatureTypeList>

[…]

<FeatureType>

<Name>greenland_elevation_contours</Name>

[…]

</FeatureType>

[…]

<FeatureType>

<Name>north_poles_wfs</Name>

<Title>North Poles</Title>

<Abstract>Labels the location of various types of North Poles: geographic, geomagnetic, magnetic, pole of cold, and pole of inaccessibility. Citations: […]</Abstract>

<ows:Keywords>

<ows:Keyword>Arctic</ows:Keyword>

[…]

</ows:Keywords>

<DefaultSRS>EPSG:32661</DefaultSRS>

<OutputFormats>

<Format>text/xml; subtype=gml/3.1.1</Format>

</OutputFormats>

<ows:WGS84BoundingBox dimensions="2">

<ows:LowerCorner>-179.398145800191
67.4138497780757
</ows:LowerCorner>

<ows:UpperCorner>179.629931564272
86.7641921273786
</ows:UpperCorner>

</ows:WGS84BoundingBox>

</FeatureType>

[…]

</FeatureTypeList>

Finally, this service supports filtering features by several criteria detailed in the last section of the XML file:


<ogc:Filter_Capabilities>

<ogc:Spatial_Capabilities>

<ogc:GeometryOperands>

<ogc:GeometryOperand>gml:Point</ogc:GeometryOperand>

<ogc:GeometryOperand>gml:LineString</ogc:GeometryOperand>

<ogc:GeometryOperand>gml:Polygon</ogc:GeometryOperand>

<ogc:GeometryOperand>gml:Envelope</ogc:GeometryOperand>

</ogc:GeometryOperands>

<ogc:SpatialOperators>

<ogc:SpatialOperator name="Equals"/>

<ogc:SpatialOperator name="Disjoint"/>

<ogc:SpatialOperator name="Touches"/>

<ogc:SpatialOperator name="Within"/>

<ogc:SpatialOperator name="Overlaps"/>

<ogc:SpatialOperator name="Crosses"/>

<ogc:SpatialOperator name="Intersects"/>

<ogc:SpatialOperator name="Contains"/>

<ogc:SpatialOperator name="DWithin"/>

<ogc:SpatialOperator name="Beyond"/>

<ogc:SpatialOperator name="BBOX"/>

</ogc:SpatialOperators>

</ogc:Spatial_Capabilities>

<ogc:Scalar_Capabilities>

<ogc:LogicalOperators/>

<ogc:ComparisonOperators>

<ogc:ComparisonOperator>LessThan</ogc:ComparisonOperator>

<ogc:ComparisonOperator>GreaterThan</ogc:ComparisonOperator>

<ogc:ComparisonOperator>LessThanEqualTo</ogc:ComparisonOperator>

<ogc:ComparisonOperator>GreaterThanEqualTo</ogc:ComparisonOperator>

<ogc:ComparisonOperator>EqualTo</ogc:ComparisonOperator>

<ogc:ComparisonOperator>NotEqualTo</ogc:ComparisonOperator>

<ogc:ComparisonOperator>Like</ogc:ComparisonOperator>

<ogc:ComparisonOperator>Between</ogc:ComparisonOperator>

</ogc:ComparisonOperators>

</ogc:Scalar_Capabilities>

<ogc:Id_Capabilities>

<ogc:FID/>

</ogc:Id_Capabilities>

</ogc:Filter_Capabilities>

2.2.3.2 Describing Your FeatureTypes: The DescribeFeatureType operation

So far we have been discussing data models in GML and the way to describe them in XML application schemas. DescribeFeatureType is used to obtain application schemas.

2.2.3.2.1 DescribeFeatureType request

To build a DescribeFeatureType request we use the server URL http://nsidc.org/cgi-bin/atlas_north and, for the WFS version 1.1, and adding "?service=WFS&request=DescribeFeatureType&version=1.1.0&typename=". Then, we have two situations:

• We leave the request like this. Then, we are going to get all feature types in the response.
• We add a list of feature type names separated by comas. FeatureType names can be found on the capabilities document for the content of the elements "/wfs:WFS_Capabilities/FeatureTypeList/FeatureType[]/Name".

In our example, we are going to use: north_poles_wfs and greenland_elevation_contours. A valid request to this server is:

http://nsidc.org/cgi-bin/atlas_north...ation_contours

2.2.3.2.2 DescribeFeatureType response: GML application schema

The response to a well formed DescribeFeatureType request is a GML application schema for the requested types. In our example we are getting:


<schema

targetNamespace="http://mapserver.gis.umn.edu/mapserver"

xmlns:ms="http://mapserver.gis.umn.edu/mapserver"

xmlns:ogc="http://www.opengis.net/ogc"

xmlns="http://www.w3.org/2001/XMLSchema"

xmlns:gml="http://www.opengis.net/gml"

elementFormDefault="qualified" version="0.1">

 

<import namespace="http://www.opengis.net/gml"

schemaLocation="http://schemas.opengis.net/gml/3.1.1/base/gml.xsd"/>

 

<element name="greenland_elevation_contours"

type="ms:greenland_elevation_contoursType"

substitutionGroup="gml:_Feature"/>

 

<complexType name="greenland_elevation_contoursType">

<complexContent>

<extension base="gml:AbstractFeatureType">

<sequence>

<element name="msGeometry" type="gml:GeometryPropertyType" minOccurs="0" maxOccurs="1"/>

<element name="Label" type="string"/>

<element name="Elevation" type="string"/>

</sequence>

</extension>

</complexContent>

</complexType>

 

<element name="north_poles_wfs"

type="ms:north_poles_wfsType"

substitutionGroup="gml:_Feature"/>

 

<complexType name="north_poles_wfsType">

<complexContent>

<extension base="gml:AbstractFeatureType">

<sequence>

<element name="msGeometry" type="gml:GeometryPropertyType" minOccurs="0" maxOccurs="1"/>

<element name="Id" type="string"/>

<element name="NAME" type="string"/>

</sequence>

</extension>

</complexContent>

</complexType>

 

</schema>


In previous sections we have discussed about data models and the translation into GML applications schemas. This application schema for the north_poles example has already been explained. A particular problem that occurs when implementing it, is that the gml:GeometryPropertyType hides the actual geometric objects used to describe both feature types. We already know that north_poles will be expressed as GML points and we suppose that greenland_elevation_contoursType will be expressed as GML linestrings, but we can not confirm it until we actually request the features. This is why we would recommend that a more concrete subclass of gml:AbstractFeatureType was used instead. It is also surprising that "Elevation" has a "string" type valure since we expect numbers in it.

2.2.3.3 Serving a Feature collection: The GetFeature operation

This operation allows us to retrieve a subset of the features that the WFS stores.

2.3.3.1 Implementing GetFeature: Required Parameters

To build a DescribeFeatureType request we use the server URL http://nsidc.org/cgi-bin/atlas_north and, for the WFS version 1.1, we add "http://nsidc.org/cgi-bin/atlas_north....1.0&typename=". Then we add a coma separated list of feature type names. FeatureType names can be found on the capabilities document for the content of the elements "/wfs:WFS_Capabilities/FeatureTypeList/FeatureType[]/Name".
In our example, we use: north_poles_wfs or greenland_elevation_contours.
Request of features for both feature types will be something like this:

http://nsidc.org/cgi-bin/atlas_north...orth_poles_wfs

and

http://nsidc.org/cgi-bin/atlas_north...ation_contours


2.2.3.3.2 GetFeature Response. GML data

The response to a well formed GetFeature request is a GML application schema for the requested types. In our first example we get:


<wfs:FeatureCollection xmlns:ms="http://mapserver.gis.umn.edu/mapserver" xmlns:gml="http://www.opengis.net/gml" xmlns:wfs="http://www.opengis.net/wfs" xmlns:ogc="http://www.opengis.net/ogc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://mapserver.gis.umn.edu/mapserver http://nsidc.org/cgi-bin/atlas_north...orth_poles_wfs http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.1.0/wfs.xsd">

<gml:boundedBy>

<gml:Envelope srsName="EPSG:32661">

<gml:lowerCorner>903627.830798 1639531.171915</gml:lowerCorner>

<gml:upperCorner>3845580.759766 3744059.030924</gml:upperCorner>

</gml:Envelope>

</gml:boundedBy>

<gml:featureMember>

<ms:north_poles_wfs gml:id="north_poles_wfs.0">

<gml:boundedBy>

<gml:Envelope srsName="EPSG:32661">

<gml:lowerCorner>

2000000.000000 2000000.000000</gml:lowerCorner>

<gml:upperCorner>

2000000.000000 2000000.000000</gml:upperCorner>

</gml:Envelope>

</gml:boundedBy>

<ms:msGeometry>

<gml:Point srsName="EPSG:32661">

<gml:pos>2000000.000000 2000000.000000</gml:pos>

</gml:Point>

</ms:msGeometry>

<ms:Id>0</ms:Id>

<ms:NAME>Geographic North Pole</ms:NAME>

</ms:north_poles_wfs>

</gml:featureMember>

<gml:featureMember>

<ms:north_poles_wfs gml:id="north_poles_wfs.1">

[…]

<ms:msGeometry>

<gml:Point srsName="EPSG:32661">

<gml:pos>1256015.530206 2337486.323100</gml:pos>

</gml:Point>

</ms:msGeometry>

<ms:Id>0</ms:Id>

<ms:NAME>Magnetic North Pole (2005)</ms:NAME>

</ms:north_poles_wfs>

</gml:featureMember>

<gml:featureMember>

[…]

</gml:featureMember>

</wfs:FeatureCollection>


It is interesting to see that the xsi:schemaLocation of the GML application schema is a dynamically generated document that is in fact a DescribeFeatureType request, which will return a GML application schema for these features.

Sometimes things do not work fully as expected. The complete response from the WFS service does not validate in XMLSpy. This is due to some mismatching problems, firstly, the DescribeFeatureType has an optional parameter OutputFormat=text/xml; subtype=gml/3.1.1 (with a space in it), this makes the schema location unreadable. We can fix this by removing this optional parameter, leaving the default value as indicated. Secondly, all gml_id attributes were set to "0", XMLSpy detects this as a violation of the uniqueness of the identifier. The xml fragment illustrated here fixes both issues.

In our second example we get:

<wfs:FeatureCollection xmlns:ms="http://mapserver.gis.umn.edu/mapserver" xmlns:gml="http://www.opengis.net/gml" xmlns:wfs="http://www.opengis.net/wfs" xmlns:ogc="http://www.opengis.net/ogc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://mapserver.gis.umn.edu/mapserver http://nsidc.org/cgi-bin/atlas_north...ation_contours http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.1.0/wfs.xsd">

[…]

<gml:featureMember>

<ms:greenland_elevation_contours>

<gml:boundedBy>

<gml:Envelope srsName="EPSG:32661">

<gml:lowerCorner>

-327189.501776 -456661.863393</gml:lowerCorner>

<gml:upperCorner>

-327164.993574 -456636.649888</gml:upperCorner>

</gml:Envelope>

</gml:boundedBy>

<ms:msGeometry>

<gml:LineString srsName="EPSG:32661">

<gml:posList srsDimension="2">-327164.993574 -456638.840870 -327189.501776 -456636.649888 -327183.636846 -456661.863393 -327168.660334 -456653.526955 -327164.993574 -456638.840870 </gml:posList>

</gml:LineString>

</ms:msGeometry>

<ms:Label>1000 m</ms:Label>

<ms:Elevation>1000.000000</ms:Elevation>

</ms:greenland_elevation_contours>

</gml:featureMember>

<gml:featureMember>

<ms:greenland_elevation_contours>

[…]

</gml:featureMember>

[…]

</wfs:FeatureCollection>

 

As expected, the second example has a geometric element of the gml:LineStringType (a sequence of coordinates). Also, the "Elevation" is a decimal number so it would be better to use xs:decimal instead of xs:string in the definition of the greenland_elevation_contours type.

2.2.3.4. Exceptions

Sometimes the client does not provide a well formed supported request or for some reason, the service is not able to perform the requested task. Under these circumstances, the service will respond with an XML file that explains the origin of the problem.

For example, if we send a GetCoverage request to a WFS service:

<ows:ExceptionReport xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ows="http://www.opengis.net/ows/1.1" version="1.1.0" xml:lang="en-US" xsi:schemaLocation="http://www.opengis.net/ows/1.1 http://schemas.opengis.net/ows/1.1.0...tionReport.xsd">

<ows:Exception exceptionCode="request" locator="InvalidParameterValue">

<ows:ExceptionText>msWFSDispatch(): WFS server error. Invalid WFS request: GetCoverage</ows:ExceptionText>

</ows:Exception>

</ows:ExceptionReport>


http://nsidc.org/cgi-bin/atlas_north...&version=1.1.0 it will generate an exception like this:


The sentence: "Invalid WFS request: GetCoverage" reveals the reason of the problem.

• If the origin of the problem is in our side, we could try to identify it and fix it.
• If the origin of the problem is not in our side, there isn't much to be done except to contact the service provider using the contact information available in the ServiceProvider section of the capabilities document.


This is an example of a situation where we cannot fix the problem:


<ows:ExceptionReport>

<ows:Exception exceptionCode="NoApplicableCode">

<ows:ExceptionText>java.io.FileNotFoundException: Shapefile not found:file:/usr/local/geoserver/data_dir/data/sibessc/external/iiasa_landresourc/soils/soilnat_dd.shp</ows:ExceptionText>

</ows:Exception>

</ows:ExceptionReport>

The exception report seems to suggest a missing file, but since we do not have access to the service file system, we cannot fix the problem ourselves. This problem was found in the Siberian Earth System Science Cluster WFS service (CSR urn:uuid:1fc2a913-7739-48e2-8222-d1fd2e2f79fd) trying to test a GetGmlObject operation.

<<Prev T.O.C.  Next>>

Tag
none

Files (0)

 
You must login to post a comment.