WMS Support

App-schema supports WMS requests as well as WFS requests. This page provides some useful examples for configuring the WMS service to work with complex features.

Note that the rendering performance of WMS can be significantly slower when using app-schema data stores. We strongly recommend employing Joining Support For Performance when using WMS with feature chaining, which can make response time for large data requests several orders of magnitude faster.


For WMS to be applicable to complex feature data, it is necessary that the complex feature types are recognised by GeoServer as layers. This must be configured by adding an extra configuration file named ‘layer.xml’ in the data directory of each feature type that we want to use as a WMS layer.

This will expand the structure of the workspaces folder in the GeoServer data directory as follows (workspaces) (see Configuration):

    - gsml
        - SomeDataStore
            - SomeFeatureType
                - featuretype.xml
                - layer.xml
            - datastore.xml
            - SomeFeatureType-mapping-file.xml

The file layer.xml must have the following contents:

  <resource class="featureType">

Replace the fields in between brackets with the following values:

  • [mylayerid] must be a custom id for the layer.

  • [mylayername] must be a custom name for the layer.

  • [mydefaultstyle] the default style used for this layer (when a style is not specified in the wms request). The style must exist in the GeoServer configuration.

  • [myfeaturetypeid] is the id of the feature type. This must the same as the id specified in the file featuretype.xml of the same directory.


Read GetMap for general information on the GetMap request. Read Styling for general information on how to style WMS maps with SLD files. When styling complex features, you can use XPaths to specify nested properties in your filters, as explained in Filtering nested attributes on chained features. However, in WMS styling filters X-paths do not support handling referenced features (see Multi-valued properties by reference (xlink:href)) as if they were actual nested features (because the filters are applied after building the features rather than before.) The prefix/namespace context that is used in the XPath expression is defined locally in the XML tags of the style file. This is an example of a Style file for complex features:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <StyledLayerDescriptor version="1.0.0"
 3     xsi:schemaLocation="http://www.opengis.net/sld StyledLayerDescriptor.xsd"
 4     xmlns:ogc="http://www.opengis.net/ogc"
 5     xmlns:xlink="http://www.w3.org/1999/xlink"
 6     xmlns:gml="http://www.opengis.net/gml"
 7     xmlns:gsml="urn:cgi:xmlns:CGI:GeoSciML:2.0"
 8     xmlns:sld="http://www.opengis.net/sld"
 9     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
10  <sld:NamedLayer>
11   <sld:Name>geology-lithology</sld:Name>
12   <sld:UserStyle>
13     <sld:Name>geology-lithology</sld:Name>
14     <sld:Title>Geological Unit Lithology Theme</sld:Title>
15     <sld:Abstract>The colour has been creatively adapted from Moyer,Hasting
16          and Raines, 2005 (http://pubs.usgs.gov/of/2005/1314/of2005-1314.pdf)
17          which provides xls spreadsheets for various color schemes.
18          plus some creative entries to fill missing entries.
19     </sld:Abstract>
20     <sld:IsDefault>1</sld:IsDefault>
21     <sld:FeatureTypeStyle>
22       <sld:Rule>
23         <sld:Name>acidic igneous material</sld:Name>
24         <sld:Abstract>Igneous material with more than 63 percent SiO2.
25                        (after LeMaitre et al. 2002)
26         </sld:Abstract>
27         <ogc:Filter>
28           <ogc:PropertyIsEqualTo>
29             <ogc:PropertyName>gsml:specification/gsml:GeologicUnit/gsml:composition/
30                  gsml:CompositionPart/gsml:lithology/@xlink:href</ogc:PropertyName>
31             <ogc:Literal>urn:cgi:classifier:CGI:SimpleLithology:200811:
32                          acidic_igneous_material</ogc:Literal>
33           </ogc:PropertyIsEqualTo>
34         </ogc:Filter>
35         <sld:PolygonSymbolizer>
36           <sld:Fill>
37             <sld:CssParameter name="fill">#FFCCB3</sld:CssParameter>
38           </sld:Fill>
39         </sld:PolygonSymbolizer>
40       </sld:Rule>
41       <sld:Rule>
42         <sld:Name>acidic igneous rock</sld:Name>
43         <sld:Abstract>Igneous rock with more than 63 percent SiO2.
44                      (after LeMaitre et al. 2002)
45         </sld:Abstract>
46         <ogc:Filter>
47           <ogc:PropertyIsEqualTo>
48             <ogc:PropertyName>gsml:specification/gsml:GeologicUnit/gsml:composition/
49                  gsml:CompositionPart/gsml:lithology/@xlink:href</ogc:PropertyName>
50             <ogc:Literal>urn:cgi:classifier:CGI:SimpleLithology:200811:
51                          acidic_igneous_rock</ogc:Literal>
52             </ogc:PropertyIsEqualTo>
53         </ogc:Filter>
54         <sld:PolygonSymbolizer>
55           <sld:Fill>
56             <sld:CssParameter name="fill">#FECDB2</sld:CssParameter>
57           </sld:Fill>
58         </sld:PolygonSymbolizer>
59       </sld:Rule>
60       ...
61     </sld:FeatureTypeStyle>
62   </sld:UserStyle>
63  </sld:NamedLayer>
64 </sld:StyledLayerDescriptor>


Read GetFeatureInfo for general information on the GetFeatureInfo request. Read the tutorial on GetFeatureInfo Templates for information on how to template the html output. If you want to store a separate standard template for complex feature collections, save it under the filename complex_content.ftl in the template directory.

Read the tutorial on Freemarker Templates for more information on how to use the freemarker templates. Freemarker templates support recursive calls, which can be useful for templating complex content. For example, the following freemarker template creates a table of features with a column for each property, and will create another table inside each cell that contains a feature as property:

Macro's used for content

<#macro property node>
    <#if !node.isGeometry>
      <#if node.isComplex>
      <td> <@feature node=node.rawValue type=node.type /> </td>

<#macro header typenode>
<caption class="featureInfo">${typenode.name}</caption>
<#list typenode.attributes as attribute>
  <#if !attribute.isGeometry>
    <#if attribute.prefix == "">
        <th >${attribute.name}</th>
        <th >${attribute.prefix}:${attribute.name}</th>

<#macro feature node type>
<table class="featureInfo">
  <@header typenode=type />
  <#list node.attributes as attribute>
      <@property node=attribute />

Body section of the GetFeatureInfo template, it's provided with one feature collection, and
will be called multiple times if there are various feature collections
<table class="featureInfo">
  <@header typenode=type />

<#assign odd = false>
<#list features as feature>
  <#if odd>
    <tr class="odd">
  <#assign odd = !odd>

  <#list feature.attributes as attribute>
    <@property node=attribute />