Git Product home page Git Product logo

maps4html / geoserver Goto Github PK

View Code? Open in Web Editor NEW

This project forked from geoserver/geoserver

3.0 3.0 1.0 283.01 MB

Maps for HTML MapML Extension / plug-in development fork of GeoServer

Home Page: https://docs.geoserver.org/latest/en/user/extensions/mapml/index.html

License: Other

Shell 0.07% Python 0.04% Scheme 2.17% Batchfile 0.03% HTML 1.43% XSLT 0.33% JavaScript 2.38% CSS 0.23% Java 92.71% FreeMarker 0.49% Makefile 0.01% NSIS 0.09% AMPL 0.02% Fluent 0.01% Dockerfile 0.01%
geoserver java mapml mapping maps web web-mapping wfs wms wmts

geoserver's People

Contributors

aaime avatar bencaradocdavies avatar bjornharrtell avatar bmmpxf avatar bradh avatar dblasby avatar dependabot[bot] avatar dromagnoli avatar etj avatar fernandor777 avatar fgdrf avatar groldan avatar ianturton avatar imranrajjad avatar jdeolive avatar jmarin avatar jnh5y avatar jodygarnett avatar mbarto avatar moesol avatar mprins avatar n-lagomarsini avatar nielscharlier avatar petersmythe avatar riniangreani avatar sikeoka avatar smithkm avatar svzdvd avatar taba90 avatar tbarsballe avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

Forkers

prushforth

geoserver's Issues

GetMap with format=text/mapml returns <map-extent> with rel=features for vector data

Background

The set of requirements surrounding GetMap in this document, taken together, will reconstitute the GeoServer MapML Extension as part of the standard WMS request/response protocol, so that MapML clients can interact with the richness of the OGC WMS implementation provided by the GeoServer geospatial CMS, while simultaneously benefiting from the (proposed) standardized client map and location semantics.

Requirement

Related to #50 and #48 , there should be a checkable option for "Use Features" (default un-checked) in the MapML Settings panel for a layer (not for layer groups) that changes the serialized <map-link rel="image" ...> to <map-link rel="features">, as described below.

For a raster data source, the "Use Features" option must be disabled / uncheckable. For vector data, the default should be unchecked, but it should be enabled and checkable if "Use Tiles" is unchecked.

image

When "Use Features" is checked for a layer based on a vector-capable data source, the response from GetMap for the layer should be a MapML document in which the <map-extent> contains a link URL template with rel="features" and in which the GetMap format_options parameter is set, as described below.

When a GetMap for multiple layers and styles happens, a question of how to handle differently set "Use Vectors" layers in the request layers list arises.

There are two proposed ways of representing individual layers in a multi-layer GetMap.

  1. A multi-layer, multi-style GetMap MapML format response embodied by one <map-extent>
  2. A multi-layer, multi-style GetMap MapML format response with one <map-extent> per layer

For 1. above, if there is a heterogeneity of "Use Features" states (some checked, some unchecked) among the different layers in the request, "Use Features" must be ignored for the request and a single link URL template emitted with rel="image":

<map-link rel="image" tref="https://example.org/geoserver/wms?request=GetMap&layers=a,b,c&format=image/png..."><map-link>

For 1. above, on the other hand, if all of the layers in the request have "Use Features" checked i.e., the set of requested layers has a homogeneous collection of "Use Features" (state = checked) among the different layers in the request, then the response link template, which would otherwise have a rel="image" value, will be serialized with a rel="features" and type="text/mapml" state and with a GetMap URL (template) whose format_options value is set to mapmlfeatures:true. See GetMap format_options MapML requirement

<map-link rel="features" type="text/mapml" tref="https://example.org/geoserver/wms?request=GetMap&layers=a,b,c&format=text/mapml&format_options=mapmlfeatures:true..."><map-link>

For 2. above, since each layer is serialized as its own <map-extent> with associated link URL template, those layers which have "Use Features" checked must be serialized with a link URL template <map-link rel="features" and type="text/mapml" ...> state, and a URL template whose format_options value is set to mapmlfeatures:true.

Maintain "Use Tiles"

In the current MapML extension, the "Use Tiles" checkbox governs how requests for the current layer is interpreted for the purpose of serializing a <map-extent>. Without vector support (which clearly continues to be the case for a raster data source, and ignoring for the moment the existing WFS MapML integration), "Use Tiles" is interpreted according to the what is possible for the layer or layer group, given the existence or not of a compatible tile cache, established in the "Tile Caching" tab interface.

The current logic is:

if ("Use Tiles") {
  if ("Tile Caching") {
    <map-link rel="tile" tref="...GetTile..."></map-link>
  else { /* tile-shaped GetMap request template */
    <map-link rel="tile" tref="...GetMap...">
  }
else { /* entire map view generated by "traditional" GetMap, which is good for e.g. labels */
  <map-link rel="image" tref="...GetMap..."></map-link>
}

if ("Queryable")
  if ("Use Tiles" && "Tile Caching") { /* generate WMTS GetFeatureInfo request template */
    <map-link rel="query" tref="...&service=WMTS&request=GetFeatureInfo..."></map-link>
  else { /* generate WMS GetFeatureInfo request template */
    <map-link rel="query" tref="...&service=WMS&request=GetFeatureInfo..."></map-link>
  }
}

In future, because of the possibility of serializing feature content directly with a GetMap request and because that feature content may ALSO be used to create vector tiles in "text/mapml" format, it will be necessary to significantly update this logic to reflect how the "Use Tiles" and "Use Features" settings will be processed together, should they both be selected, and given the fact that a layer or layer group can be one of many layers and/or layer groups present in a GetMap layers parameter list.

Use GeoServer's minimum and maximum image generation width and height for serialized width and height inputs

Background

When generating a <map-extent> for an image-based map, the current MapML extension serializes two <map-input>s which reflect the standard width and height WMS parameter values. Such inputs are serialized to support GetMap and GetFeatureInfo request templates, and (currently) have hard-coded min and max attribute values:

...
    <map-extent  units="OSMTILE">
      <map-input name="z" type="zoom"  min="0" max="18"/>
      <map-input name="xmin" type="location" rel="map" position="top-left" axis="easting" units="pcrs" min="1.6011619366020126E7" max="1.6528622369542673E7"/>
      <map-input name="ymin" type="location" rel="map" position="bottom-left" axis="northing" units="pcrs" min="-5411138.5986247435" max="-4804213.1199940005"/>
      <map-input name="xmax" type="location" rel="map" position="top-right" axis="easting" units="pcrs" min="1.6011619366020126E7" max="1.6528622369542673E7"/>
      <map-input name="ymax" type="location" rel="map" position="top-left" axis="northing" units="pcrs" min="-5411138.5986247435" max="-4804213.1199940005"/>
      <map-input name="w" type="width" min="1" max="10000"/>
      <map-input name="h" type="height" min="1" max="10000"/>
      <!-- If the layer is queryable per the GeoServer catalog, a query link template and associated variables should be serialized -->
      <map-link  rel="image" tref="http://example.org/geoserver/wms?request=GetMap&crs=EPSG:3857&service=WMS&bbox={xmin},{ymin},{xmax},{ymax}&layers=tasmania_state_boundaries&styles=green&format=image/png&width={w}&language=en&version=1.3.0&transparent=true&height={h}"/>
      <map-input name="i" type="location" axis="i" units="map"/>
      <map-input name="j" type="location" axis="j" units="map"/>
      <map-link rel="query" tref="http://example.org/geoserver/wms?request=GetFeatureInfo&query_layers=tasmania_state_boundaries&crs=EPSG:3857&bbox={xmin},{ymin},{xmax},{ymax}&language=en&version=1.3.0&transparent=true&service=WMS&layers=tasmania_state_boundaries&width={w}&x={i}&feature_count=50&y={j}&styles=green&info_format=text/mapml&height={h}"/>
    </map-extent>
...

Requirement

All width and height inputs should be serialized with the min and max attribute values in effect for the GeoServer system, if such limits indeed exist.

(Possible) Reference

<map-input type="height" name="h" min="16" max="2048"></map-input>

Allow GeoServer user to specify that a layer group should be replicated in MapML URL templates

If you put two discontinuous GeoServer layers over the same continuous data source into a LayerGroup e.g. a satellite image of Canada is your data source and you set up two layers, one over Nova Scotia's extent and the other over the extent of British Columbia, which you then put into a LayerGroup that you call "BC & NS".

If the user makes a WMS request to the LayerGroup for a bbox that covers Canada, you will receive the full satellite image of Canada in response, not just the rectangles which bound BC and NS.

To escape this problem, MapML could serve this LayerGroup not as a single URL template that references the layer group, but as a pair of separate URL templates, each with its own location inputs, with those inputs' min/max values scoped to the bounding rectangles of the layers in the group. The MapML mapml-viewer client will only make requests against a template within the extent assigned to that template by its inputs' min/max values (example shows tilematrix extents, but could be pcrs just as well, or mixed fwiw):

<extent units="OSMTILE">
  <input name="zBC" type="zoom" value="6" min="0" max="15"/>
  <input name="yBC" type="location" units="tilematrix" axis="row" min="18" max="21"/>
  <input name="xBC" type="location" units="tilematrix" axis="column" min="7" max="11"/>
  <link rel="tile" tref="https://example.org/3857/BC/tile/{zBC}/{yBC}/{xBC}"/>

  <input name="zNS" type="zoom" value="6" min="0" max="15"/>
  <input name="yNS" type="location" units="tilematrix" axis="row" min="22" max="23"/>
  <input name="xNS" type="location" units="tilematrix" axis="column" min="20" max="21"/>
  <link rel="tile" tref="https://example.org/3857/NS/tile/{zNS}/{yNS}/{xNS}"/>
</extent>

Allow text/mapml to be available as a response format for a fully parameterized WMS GetMap request

It occurred to me that while a MapML document doesn't need to have parameters in order to be useful, it could be useful to reduce latency on the client if a GetMap request could serve content already baked into the response to a GetMap request. In other words, the response document could include <tile row="n" col="m" href="..."></tile> elements as well as an <extent> element, so that (if the client was smart enough), the initial content would be about as fast as a "server rendered" HTML response. In Testbed 14 we came to describe such a document as a static map.

Enable OUTPUTFORMAT=text/mapml and OUTPUTFORMAT=application/mapml for WFS GetFeature requests (is "MAPML")

Background

In the current MapML extension, WFS GetFeature is enabled to serve text/mapml content type when the OUTPUTFORMAT=MAPML parameter is present. This response contains a <mapml-> document containing response metadata and as many <map-feature> elements as allowed by the specified maxFeatures parameter.

Requirement

Update the GeoServer WFS so that a GetFeature request with the outputFormat=application/mapml parameter will serialize an HTML document containing a <mapml-viewer> element containing a <layer-> element that contains a <map-extent> element that contains a URL template of a GetFeature request for the OUTPUTFORMAT=text/mapml content type with a rel="features" link relation:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>MapML Features in-line as HTML layers, returned by GetFeature with "OUTPUTFORMAT=application/mapml"</title>
    <script type="module" src="../dist/mapml-viewer.js"></script>
  </head>
  <body>
  <mapml-viewer zoom="16" lon="141.5" lat="-43.3" controls projection="OSMTILE">
    <layer- label="Tasmania Cities" checked>
      <map-extent units="OSMTILE">
        <map-input name="z" type="zoom" min="0" max="18"></map-input>
        <map-input name="xmin" type="location" rel="map" position="top-left" axis="easting" units="pcrs" min="..." max="..."></map-input>
        <map-input name="ymin" type="location" rel="map" position="bottom-left" axis="northing" units="pcrs" min="..." max="..."></map-input>
        <map-input name="xmax" type="location" rel="map" position="top-right" axis="easting" units="pcrs" min="..." max="..."></map-input>
        <map-input name="ymax" type="location" rel="map" position="top-left" axis="northing" units="pcrs" min="..." max="..."></map-input>
        <map-link rel="features" tref="https://example.com/geoserver/topp/ows?TYPENAME=topp:tasmania_cities&amp;REQUEST=GetFeature&amp;OUTPUTFORMAT=text/mapml&amp;SRSNAME=OSMTILE&amp;VERSION=1.0.0&amp;MAXFEATURES=50&amp;SERVICE=WFS&BBOX={xmin},{ymin},{xmax},{ymax}"></map-link>
      </map-extent>
    </layer->
  </mapml-viewer>
  </body>
</html>

The result of a client executing a GetMap created according to the above map-link template will result in a text/mapml serialization of the actual features of the layer that respond to the specified bbox value:

<mapml- xmlns="http://www.w3.org/1999/xhtml">
  <map-head>
    <map-title>tasmania_cities</map-title>
    <map-meta charset="UTF-8" />
    <map-meta content="text/mapml" http-equiv="Content-Type" />
    <map-meta name="cs" content="gcrs" />
    <map-meta name="extent" content="top-left-longitude=145.197540,top-left-latitude=-40.852802,bottom-right-longitude=148.272980,bottom-right-latitude=-43.423512" />
    <map-meta name="projection" content="MapML:EPSG:4326" />
    <map-link href="http://example.com/geoserver/topp/ows?TYPENAME=topp:tasmania_cities&amp;REQUEST=GetFeature&amp;OUTPUTFORMAT=MAPML&amp;SRSNAME=urn:x-ogc:def:crs:EPSG:3857&amp;VERSION=1.0.0&amp;MAXFEATURES=50&amp;SERVICE=WFS" rel="alternate" projection="OSMTILE" />
    <map-link href="http://example.com/geoserver/topp/ows?TYPENAME=topp:tasmania_cities&amp;REQUEST=GetFeature&amp;OUTPUTFORMAT=MAPML&amp;SRSNAME=urn:x-ogc:def:crs:EPSG:3978&amp;VERSION=1.0.0&amp;MAXFEATURES=50&amp;SERVICE=WFS" rel="alternate" projection="CBMTILE" />
    <map-link href="http://example.com/geoserver/topp/ows?TYPENAME=topp:tasmania_cities&amp;REQUEST=GetFeature&amp;OUTPUTFORMAT=MAPML&amp;SRSNAME=urn:x-ogc:def:crs:EPSG:5936&amp;VERSION=1.0.0&amp;MAXFEATURES=50&amp;SERVICE=WFS" rel="alternate" projection="APSTILE" />
    <map-link href="http://example.com/geoserver/topp/ows?TYPENAME=topp:tasmania_cities&amp;REQUEST=GetFeature&amp;OUTPUTFORMAT=MAPML&amp;SRSNAME=urn:ogc:def:crs:OGC:1.3:CRS84&amp;VERSION=1.0.0&amp;MAXFEATURES=50&amp;SERVICE=WFS" rel="alternate" projection="WGS84" />
  </map-head>
  <map-body>
    <map-feature id="tasmania_cities.1" class="tasmania_cities">
      <map-featurecaption>Hobart</map-featurecaption>
      <map-geometry>
        <map-multipoint>
          <map-coordinates>147.291 -42.851</map-coordinates>
        </map-multipoint>
      </map-geometry>
      <map-properties>
        <table>
          <thead>
            <tr>
              <th role="columnheader" scope="col">Property name</th>
              <th role="columnheader" scope="col">Property value</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <th scope="row">CITY_NAME</th>
              <td itemprop="CITY_NAME">Hobart</td>
            </tr>
            <tr>
              <th scope="row">ADMIN_NAME</th>
              <td itemprop="ADMIN_NAME">Tasmania</td>
            </tr>
            <tr>
              <th scope="row">CNTRY_NAME</th>
              <td itemprop="CNTRY_NAME">Australia</td>
            </tr>
            <tr>
              <th scope="row">STATUS</th>
              <td itemprop="STATUS">Provincial capital</td>
            </tr>
            <tr>
              <th scope="row">POP_CLASS</th>
              <td itemprop="POP_CLASS">100,000 to 250,000</td>
            </tr>
          </tbody>
        </table>
      </map-properties>
    </map-feature>
  </map-body>
</mapml->

Add the MapML TCRS CRSs to the WFS Capabilities document, and serialize OSMTILE in "application/mapml" request responses by default.

Upgrade to mapml-viewer.js

The embedded viewer in GeoServer is based on the old polymer 1.0 polyfill, which is no longer supported, meaning that <map is="web-map" ...> is no longer portable across browsers (boo).

So we will need to replace the version of web-map-custom-element that is embedded, and replace references to web-map.html with appropriate <script type="module" src="mapml-viewer.js"></script>.

In doing so, we will need to think up another strategy for responsive fallback, since the old <map is="web-map" ...> configuration had a fallback configuration that allowed selection of a different WMS request depending on the viewport dimensions and aspect ratio. I will create a branch from the master branch to keep that code in a known location for future reference.

Post-process GetMap vector response to tag introduced bbox segments with <map-span class="bbox">

Background

In GetMap with format=text/mapml returns with rel=features for vector data it was established that MapML vector geometries returned by GetMap would be clipped to the boundary specified by the standard bbox GetMap parameter. When clipping point or line features, this process proceeds with little visual impact. When polygon or multipolygon geometry values are clipped, line segments created by the intersection of the bbox geometry with the multi/polygon being processed are introduced into the output geometry. The purpose of these line segments is to preserve the enclosure of space by the resulting polygon geometry.

A common map creation use case is to create a mosaic of GetMap image outputs, which may be accomplished by merging spatially adjacent image objects that have been previously generated, in the horizontal and vertical direction, often, but not exclusively, in a regular grid order (rows and columns). In order to create a visually continuous 2D image mosaic, the introduced line segments must have been removed or hidden during initial image rendering.

Requirement

  1. In the polygon geometries created as outputs from the GetMap clipping process in a MapML vector response form, wrap each of the introduced line segments in a <map-span class="bbox"> element. For reference see <map-span> documentation

  2. Ensure that a CSS class with a selector for bbox is present in the <map-style> element embedded in the response. The CSS rule for the bbox class should be as follows:

.bbox {
  display: none
}
  1. Ensure that WMS GetFeatureInfo for MapML vector data (at least, for WMS GetFeatureInfo requests with format=text/mapml&format_options=mapmlfeatures:true) MapML feature vector geometries are clipped, styled and processed per the requirement for GetMap, above.

Include a features template in MapML responses where applicable

In the MapML response, if WFS is enabled for a layer, then we could include a <link rel="features" tref="getFeatures URL">. This could / should go hand in hand with a client update which allows the user to control (turn on/off, transparency, other tbd) the templates' behaviour within a layer.

List of Tests

  • test that the value of HTML and MapML actually can be used
  • verify the set of parameters is correct and their values are correct for WMTS, WMS serialized url templates for tiles, images and queries. Will likely ensure a minimal working service.

Support custom projections

Background

In Implement TCRS subclass of CoordinateReferenceSystem we will implement a GeoTools class that allows (a developer) to encode the parameters of a custom TCRS and add it to GeoServer so that it is part of the Capabilities of WMS, WMTS and WFS services.

The <mapml-viewer> implements the "Custom Projections" API, with examples here and here.

Requirement

The MapML extension should allow the end user of WMS, WFS and WMTS to make standard protocol requests (GetMap, GetFeatureInfo, GetFeature, GetTile) using the relevant crs, srsName parameters with the custom TCRS name as the value, obtaining correct results in the designated TCRS.

The GeoServer MapML extension user interface should (already) allow the user to define a "custom projection" and assign it to the relevant services (WMS, WFS, WMTS), so that any layer that is requested as "text/mapml" will be serialized according to that TCRS. The MapML interface should allow layers associated to that gridset / tilematrixset to be accessed with that custom projection as an alternate, pretty much like a "well known" TCRS.

It must be possible to obtain an "application/mapml" response (i.e., with a text/html Content-type) from GeoServer that embeds the required client application (JavaScript) code to view data in the custom projection. It should be made possible for the user to designate such a response as the default layer preview MapML link from the Layer Preview page.

Zoom scaled layer templates

Background

The GeoServer MapML extension serves MapML documents that access GeoServer data stores and tile caches within a range of zoom levels that is associated to the TCRS definition i.e., the maximal zoom range, something like the following code snippet:

image

Requirement

Ensure that the zoom range that is serialized in MapML documents reflects the possible zoom range of the data requested. In the case where a MapML document is requested for a single layer or a single Layer Group, the zoom range should correspond (transformed from scale denominators to zoom level values) to the scale range for the layer or layer group from the Capabilities document (in which the scale range for the layer is reflected by the and values) OR if such values are not available for the layer/layer group, the min/max zoom values should be obtained from the TCRS in use (in the above example, “OSMTILE”).

In the case of a MapML document that is generated in response to a GetMap for multiple layers and/or layer groups, if the response corresponds to SW.4.1.3.1.txt, the zoom range that is serialized must reflect the union of the scale ranges for all the listed layers i.e., the smallest (for min) and largest (for max) denominator scales listed for all the scale denominator ranges (represented by and in the GetCapabilities response, for WMS 1.3) for all the requested layers. See file SW.4.1.10.1.txt for a commented example of this output.

In the case of a MapML document that is generated in response to a GetMap for multiple layers and/or layer groups, if the response corresponds to SW.4.1.3.2.txt (multiple map-extent elements), then the zoom input min/max attributes should be set on a per-extent basis, that is, each map-extent should contain a zoom input whose min/max attributes each reflect a zoom value calculated from the and values respectively, for the layer that is represented by the map-extent. See file SW.4.1.10.2.txt
for a commented example of this output.

Allow MapML service to use cached tiles if enabled for the layer

Each layer can be configured to cache and serve tiles in GeoServer. While the MapML panel on the Layer page allows the admin to select "Use tiles", as a checkbox, that doesn't use the tile cache if it is available. Instead it configures the MapML response to use GetMap requests to request tiles. That is good, but if the tiles are being cached, it would be even better to generate templates in the MapML document that use the pre-cached tiles i.e. tiles but not necessarily based on GetMap requests.

When setting MapML properties for a raster layer, enable mapping of one or more coverage bands to <featurecaption>

Similar to vector feature layers, it should be possible to map a coverage "band", or a concatenation of coverage bands to the <featurecaption> that is emitted when querying the coverage. Otherwise, coverage data has no accessible name and won't be correctly read to the user. For some types of coverage data, there is only one band e.g. elevation. For other types of coverage there can be more bands and so we should allow the creation of a <featurecaption> from one or more of these (in the case that one band is not meaningful e.g. an RGB value needs all three values to be a color).

Support custom dimensions

Background

Currently, the WMS dimension support in MapML is limited to time and elevation, for which MapML can be generated according to a list of specified values, serialized as a <map-select> input variable control, containing one <map-option> element per list value.

image

GeoServer supports custom dimensions, allowing you to define a dimension over any attribute of vector layers.

Requirement

MapML extension must support custom dimensions as <map-select> -containing list values as <map-option>s as a way of allowing the end user to dynamically sub-set a map from the client.

Allow linking to GeoServer-generated CSS for MapML features responses

When a request is made for a layer as vectors, it should be possible to generate the CSS URL(s) and embed it in the response as a <link rel="stylesheet" href="the URL in question">

The CSS would be generated / cached from GeoServer SLD layer styles, which would be selected by the GeoServer MapML admin via the MapML Layer panel/tab.

Enable client to request image formats other than the currently hardcoded image/png

Background

In the MapML extension, the map-link URL template is generated with a hard-coded value of "image/png" regardless of whether this format is actually available for the image or tile being requested.

Requirement

For <map-link rel="image">, enable this selection for a layer or layer group in the MapML Settings through a drop-down list of formats that are actually enabled (currently the list is in the capabilities doc). Generate the format=image/___ value based on this selection at the layer or layer group level. For <map-link rel="tile">, where the tiles are being generated by tile-shaped GetMap requests because the "Use Tiles" option is checked but there is no tile caching enabled in the "Tile Caching" tab panel, use the same selection method as for <map-link rel="image"> i.e., the list of formats that are actually enabled per the capabilities document)

For <map-link rel="tile"> where there is in fact a tile cache available, ienable the selection from a list of image formats that are being cached for the layer or layer group, where the list is specified by what image formats are checked in the "Tile Caching" tab for the layer or layer group.

Incorrect layer bounds when using GetMap-generated tile requests

The MapMLController.mapml(...) function returns incorrect axis max/min values in certain situations when the Use Tiles is checked but there exists no GeoWebCache gridSubset, so the MapMLController.mapml(...) function generates GetMap request URL templates for tiles etc. This was missed due to branch test undercoverage.

Freemarker templates for text/mapml, application/mapml formats

Background

The current MapML extension module enables GetFeatureInfo (WMS, WMTS) and GetFeature (WFS) to return vector MapML content.

Serialized map-properties' are formatted as an HTML <table>.

Requirement

Implement the ability of GeoServer to post-process GetMap, GetFeatureInfo and GetFeature MapML (text/mapml and application/mapml and/or text/html; subtype=mapml) responses with Freemarker templates, supplied to the system according to the GeoServer mechanism for Freemarker templates.

GeoServer uses freemarker.

Add MapML panel to Layer Groups page Publishing panel

Layer groups are very handy, and can be used with MapML, except that you can't configure a layer group to use tile-based map requests. To do so would require adding a MapML panel to the publishing tab on the Layer Groups page.

Add text/mapml as a legal WMTS tile format.

Background

The MapML extension currently supports image-based map tiles, and is able to generate MapML documents that leverage the GeoWebCache and WMTS interface. For any Layer or Layer Group, the user has the option to check "Use Tiles". If the layer or layer group does not have tile caching set up for MapML TCRS gridsets, the output MapML document will be configured to generate "tile-shaped GetMap" requests that conform to the TCRS gridsets. If the user checks "Use Tiles" and sets up, via the Tile Caching layer/ layer group panel, the caching of tiles according to one or more of the standard TCRS Gridsets, then the output MapML document will be configured to issue WMTS GetTile and GetFeatureInfo requests.

Requirement

If a Layer or Layer group has "Use Features" checked:

image

enable GeoWebCache caching of vector tiles in text/mapml format, relying on the results of #50 and #48, so that in the GeoServer Tile Caching Tab of the Layer or Layer Group page, the user can select "text/mapml" as an allowed tile format:

image

The "text/mapml" format should be added to tile formats available for the layer or layer group in the WMTS Capabilities document as a <Format>text/mapml</Format> element (text/mapml is already/currently a legal <InfoFormat> value in the Capabilities document). The "text/mapml" media type should also be reflected in the layer or layer group's

<ResourceURL format="text/mapml" resourceType="tile" template="...&format=text/mapml"/> URL template list.

If the "text/mapml" tile format is checked, it should only be honoured / created for known MapML TCRS Gridsets, if any are selected; this requires that the <Format>text/mapml</Format> entries mentioned above should only be associated with TileMatrixSets defined on a MapML TCRS.

Typically, CSS style rules for MapML documents are recorded in a <map-style> element that is embedded in the MapML document. In the case of MapML documents representing individual tiles, this would be inefficient, repeating the same styles over and over for each tile. For the purpose of tile generation GetMap requests, the format_parameters="mapmltile:true" parameter should be used, which suppresses the generation of the <map-style> element, and which may in future imply other tile optimizations.

The mapmltile:true value should be specifiable via the Tile Caching panel for Layers or Layer Groups:

image

When cascading remote layer with multiple styles, not all selected styles point to all the values available

This may be related to how GeoServer handles default remote styles when populating the layer styles dialog for cascaded styles:

image

In the above image, no / blank default remote style is selected from the dropdown, while both available styles are 'selected' i.e. pushed into the selected list box.

The resulting MapML document has generated alternate style links, but the 'default' style gets selected

<link href="http://localhost:8081/geoserver/mapml/nrcan:dtm-slope/osmtile?style=slope_grey" rel="style" title="slope_grey" >
<link href="http://localhost:8081/geoserver/mapml/nrcan:dtm-slope/osmtile?style=slope_color" rel="style" title="slope_color" >
<link href="http://localhost:8081/geoserver/mapml/nrcan:dtm-slope/osmtile?style=" rel="self style" title="" >

which looks bad, because you haven't selected a value for the default style, it treats a null string as the style name:

image

When you select one of the options that is not null string as the default style, it does indeed show these options correctly in the first response:

image

results in

<link href="http://localhost:8081/geoserver/mapml/nrcan:dtm-slope/osmtile?style=slope_color" rel="style" title="slope_color">
<link href="http://localhost:8081/geoserver/mapml/nrcan:dtm-slope/osmtile?style=" rel="self style" title="slope_grey">

which correctly generates the styles options in the client:

image

but the bug appears when you select one of those options in the client, which follows the generated link to (in this case) style=slope_color, which returns a MapML document containing only this link:

<link href="http://localhost:8081/geoserver/mapml/nrcan:dtm-slope/osmtile?style=slope_color" rel="self style" title="slope_color">

when it should also contain a link to the slope_grey style from which the user navigated.

The above behaviour seems to be different than that which occurs when you select alternate styles for a local layer, for example the states shapefile has many available styles:

image

which results in a MapML document containing:

<link href="http://localhost:8081/geoserver/mapml/topp:states/osmtile?style=pophatch" rel="style" title="pophatch" />
<link href="http://localhost:8081/geoserver/mapml/topp:states/osmtile?style=polygon" rel="style" title="polygon" />
<link <href="http://localhost:8081/geoserver/mapml/topp:states/osmtile?style=" rel="self style" title="population" />

Which correctly generates the options and when you follow one of the options, the return links are also correctly generated as options:

<link href="http://localhost:8081/geoserver/mapml/topp:states/osmtile?style=polygon" rel="style" title="polygon" />
<link href="http://localhost:8081/geoserver/mapml/topp:states/osmtile?style=population" rel="style" title="population" />
<link href="http://localhost:8081/geoserver/mapml/topp:states/osmtile?style=pophatch" rel="self style" title="pophatch" />

Allow geoserver admin to set the default projection MapML URL

Background

Currently, the default URL defaults to OSMTILE, but if the data is not available in OSMTILE (or any other supported projection), this can cause errors and confusion. There should be a way to select the default projection to which the Layer Preview page's "MapML" link points.
image

Requirement

Adding a way to specify what projections / what the default projection for the link(s) are should be available on the MapML publishing panel:

image

GetMap with format=text/mapml AND format_options=mapmlfeatures:true returns styled vector MapML content

Background

The WFS GetFeature operation can return vector geospatial data in a wide variety of formats. This operation is suitable for simple use cases in which the scale of the features is fixed for use in simple data processing scenarios. GetFeature in GeoServer WFS already has the ability to serve MapML documents.

On the other hand, styled and scale-appropriate vector information cannot be obtained from WFS; for this reason the WMS GetMap operation is useful for obtaining underlying vector information that can be styled by the client, potentially reducing the processing burden on the server while providing the separation of concerns that good data management requires. Further, the GetMap operation is scale-specific, allowing not only scale-dependent styling of features, but even different geometric representations of features at different scales e.g. looking at Paris on a very small scale map, it could reasonably be represented by a point marker, while looking at the same location on a large scale map might stop representing "Paris" as such and replace that representation with street-level information.

GeoServer WMS has the ability to represent geospatial data in a scale-appropriate way, by applying symbology encoding scale-dependent rules via Styled Layer Descriptor documents. Sophisticated symbology rules enable the server to process and to even render different layer data at different scales when requested via GetMap. Typically this results in the rendering of a map image on the server side which is returned to the client via HTTP response as an image encoding of the map. Processing (including clipping, buffering and so on) and styling (applying symbology encoding rules to control rendering) of vector information is fundamental to the map creation process. An example of vector output of this processing is currently given by the ability of GeoServer to render maps in the SVG vector image format that are clipped to the bounding box of the request an decorated with CSS style rules that are derived from the applicable SLD/SE.

Requirement

This requirement enables GeoServer to respond to GetMap requests for text/mapml document representations of layers with CSS-styled MapML response documents containing appropriate-scale vector feature data.

mapmlfeatures: true | false

See format_options for GeoServer.

A suggested mechanism to distinguish what MapML content is expected for the text/mapml format GetMap response is to enable a format_options parameter value applicable to the text/mapml format when it is requested via GetMap. The state of this parameter value could indicate (a preference for) how a (vector-capable) layer is expected to be represented in the text/mapml MapML document body generated by GeoServer: either as a <map-extent> hypermedia control (mapmlfeatures:false / not present) that itself contains a URL template (in a <map-link tref> element attribute) to a GetMap that returns features (the generated URL template would contain mapmlfeatures:true), or as one or more <map-feature> elements (which would presumably be the response to the aforementioned GetMap that returns features).

This GetMap requirement is to recognize a text/mapml-specific, boolean format_options value named (subject to discussion) mapmlfeatures. Legal values: true and false. Default value (when not present) is false. When the user selects "Use Features" from the layer configuration GUI, a <map-extent> containing a URL template is created in a response to a GetMap for a text/mapml MapML document (with no / false format_options=mapmlfeatures:___ parameter value), the format_options parameter will be set in the URL template with the true value.

The logic to implement this requirement should take into account what is a "reasonable" serialization for the layer or layer group given the nature of the GetMap request and the "Use Features" and "Use Tiles" settings. If the request is for multiple layers, with associated named styles, it may be necessary to override or ignore the layer or layer group "Use Features" and "Use Tiles" settings so that the resulting map image or MapML document is coherent and useful. The detailed implementation logic will be developed and refined in the context of the other GetMap-related requirements.

image

GetMap response snippet for (single) layer with format=text/mapml with "Use Features" checked (note format_options):

...
    <map-extent units="OSMTILE">
      ...
      <map-link rel="features" tref="http://example.org/mapserver/wms?request=GetMap&amp;format=text/mapml&amp;format_options="mapmlfeatures:true" />
     ...
    </map-extent>

GetMap response snippet for (single) layer response from the above GetMap URL template:

<mapml- xmlns="http://www.w3.org/1999/xhtml">
  <map-head>...</map-head>
  <map-body>
        <map-feature id="restaurant_polygon.20" class="restaurant_polygon">
          <map-featurecaption>The Prescott</map-featurecaption>
            <map-geometry>
              <map-point>
                  <map-coordinates>-75.7093517 45.4005727</map-coordinates>
              </map-point>
            </map-geometry>
            <map-properties>
                  ....
            </map-properties>
          </map-feature>
         ...
  </map-body>
</mapml->

mapmltile: true | false

If the layer is associated to a style, either by default or by an associated named style in the styles parameter list of style names, the <map-feature> elements' descendants must be attributed with classes which have CSS style rules based on the associated named style. If the format_options mapmltile value is not present in the request or is set to false (the default), a <map-style> element must be embedded in the the root <mapml-><map-head> element and contain the CSS style rules of the associated named style. When generating MapML vector tiles (for caching, or dynamically), it is not desirable to generate a <map-style> element in each tile's MapML document.

Where the GetMap request lists multiple layers, with every layer in the request having "Use Features" enabled, the vector content and associated styles should be appended/merged into a single well-formed MapML response document, following the same order in which layers are listed in the request layers parameter.

The returned vector data must be clipped to the supplied bbox, per GetMap semantics (clip behaviour can be seen with SVG response vector format).

Error processing coordinates too close to 90 degrees (N/S)

When browsing MapML previews for various projections, there is a bug that results in a server console log message of

"20 Apr. 17:20:11 ERROR [geoserver.rest] - Latitude 90°00.0'S is too close to a pole.
org.geotools.referencing.operation.projection.ProjectionException: Latitude 90°00.0'S is too close to a pole."

The resulting MapML preview layer has an undefined name in the layer control,:

image

and no graphics show up for the layer. In the browser console, you'll see

Failed to load resource: the server responded with a status of 500 ()

something like the following:

image

This is a server side bug that needs fixing, and tests.

GitHub action to get the latest mapml-viewer

When a push comes to this repo on a particular branch perhaps not main, but maybe mapml, the latest version of the mapml-viewer build should be integrated into the mapml extension in the specific branch.

An issue would be that the upstream project requires PRs to be in the form of single commits, but if we add a commit on push here, we would need to auto squash that commit with other commits that were pushed before it, although squashing commits could be outside the scope of the required action. Typically I do that manually just prior to submitting the PR.

Another issue is that the latest mapml-viewer doesn't exist on the web-map-custom-element repo, it needs to be built, which maybe isn't a big deal since this is an action and that's what they do. i.e. the action could pull the latest and build locally.

Finally, another issue is that each file in the viewer has a custom license header, which would need to be obtained from somewhere when merging because it is obliged to be part of files included in GeoServer. @ahmadayubi can you respond on how you think this might be done or if it's too much trouble?

Thanks

Refactor MapML MVC controller as GetMap-based operation with standard parameter format=text/mapml

Background

The GeoServer MapML extension is implemented as a custom Spring MVC controller that implements two main methods at one URL end point. The MVC controller end point is currently found at:

https://example.org/geoserver/mapml/topp:states/osmtile/

Where the /mapml step represents the controller base and the /topp:states represents the layer name and /osmtile denotes the MapML (custom) TCRS.

The first method, expected to be executed by default when the above URL end point is accessed by a Web browser, returns a text/html media type as its response (because the browser negotiates for this format). This method serializes a default MapML client Web page that embeds the custom element, JavaScript, and CSS resources required to initiate a mapping application on the browser. When the HTML response is loaded by the browser, the embedded custom mapping element code will request the exact same URL from the GeoServer MapML API, but the custom application will negotiate that the URL response be returned with the text/mapml content / media type. This request is mapped to the second method in the controller, one which is coded to return the MapML document representing a single layer or layer group. Detailed custom logic is embedded in this method, and it is this logic that is to be refactored and repurposed in the form of standard GetMap-based WMS operation with the format=text/mapml parameter.

Requirement

Migrate the MapML MVC controller functionality to GetMap-based service access. Upgrade dependencies as required. Refactor the implementations of Spring MVC Controller methods as GetMap-based access. Define a (new) “application/mapml” WMS format parameter value, like the existing “application/openlayers” WMS format parameter value (which responds with "text/html; subtype=openlayers"), that is used by the GeoServer GetMap layer/layergroup “OpenLayers” preview link today. Replace the “MapML” Layer Preview screen link that is displayed by the MapML extension, with a link to a GetMap request with the “application/mapml” format parameter value, which will return an HTML page with a MapML JavaScript client application built-in (again, like how the “OpenLayers” preview link works with a Content-type: text/html response header). Define “text/mapml” as a standard response content type available for GetMap and GetFeatureInfo requests (the latter already exists).

image

For GetMap requests that refer to a single layer or layer group, the existing REST controller methods provide good exemplars of the logic required to serialize MapML for single layer requests. Tests exist which validate that the content of the MapML document as serialized reflects expectations (although they don’t “validate” the document according to an XML schema). It is a requirement that these tests be refactored to support equivalent single layer/layer group GetMap requests.

Additionally, since standard GetMap supports a comma-separated list of layers/layer groups and a parallel comma-separated list of styles to apply to those layers, GeoServer should be extended by this requirement to support MapML format responses for multi-layer, multi-style requests. A global GeoServer MapML Publishing panel option in GeoServer's WMS Settings page should allow the administrator to select how layers or layer groups should be represented in a multi-layer request. There should be two options available: 1) as a single element in which the template value contains comma-separated lists of layers/layer groups and styles (the default, unchecked value), respectively, or 2) as multiple, independent elements, one per layer or layer group in the request list.

image

Error instantiating org.geoserver.mapml.gwc.gridset.MapMLGridsets

Picking back up on work that I began at the OSGEO code sprint in November, I rebased a few commits in a feature branch for the MapML community module onto the HEAD of master branch, if I understand all that git witchcraft correctly. The application builds ok, but when deploying, it fails when trying to construct a bean that uses the GWC.get() to obtain a reference to geowebcache, which generates a NPE from this line.

Here's a bit of the stack trace:

16 Jan. 15:13:16 INFO [config.GeoserverXMLResourceProvider] - Will look for 'geowebcache.xml' in directory 'C:\Users\prushfor\Documents\catalina-base-2\webapps\geoserver\data\gwc'.
16 Jan. 15:13:16 ERROR [geowebcache.GeoWebCacheExtensions] - bean lookup error
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mapMLGridsets' defined in URL [jar:file:/C:/Users/prushfor/Documents/catalina-base-2/webapps/geoserver/WEB-INF/lib/gs-mapml-2.19-SNAPSHOT.jar!/applicationContext.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.geoserver.mapml.gwc.gridset.MapMLGridsets]: Constructor threw exception; nested exception is java.lang.NullPointerException
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1302)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1196)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:226)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:611)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:599)
	at org.springframework.context.support.AbstractApplicationContext.getBeansOfType(AbstractApplicationContext.java:1227)
	at org.geowebcache.GeoWebCacheExtensions.getBeansNamesOrderedByPriority(GeoWebCacheExtensions.java:155)
	at org.geowebcache.GeoWebCacheExtensions.extensions(GeoWebCacheExtensions.java:100)
	at org.geowebcache.GeoWebCacheExtensions.configurations(GeoWebCacheExtensions.java:203)
	at org.geowebcache.grid.GridSetBroker.getConfigurations(GridSetBroker.java:234)
	at org.geowebcache.grid.GridSetBroker.afterPropertiesSet(GridSetBroker.java:66)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1830)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1767)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:593)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:226)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
	at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:277)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1271)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1191)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:670)
	at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:376)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1404)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:592)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:226)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
	at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:303)
	at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:110)
	at org.springframework.beans.factory.support.ConstructorResolver.resolveConstructorArguments(ConstructorResolver.java:676)
	at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:188)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1340)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1186)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:226)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
	at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:303)
	at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:110)
	at org.springframework.beans.factory.support.ConstructorResolver.resolveConstructorArguments(ConstructorResolver.java:676)
	at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:188)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1340)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1186)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:226)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
	at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1106)
	at org.geoserver.platform.GeoServerExtensions.getBean(GeoServerExtensions.java:209)
	at org.geoserver.platform.GeoServerExtensions.extensions(GeoServerExtensions.java:126)
	at org.geoserver.platform.GeoServerExtensions.extensions(GeoServerExtensions.java:241)
	at org.geoserver.config.GeoServerLoader.loadInitializers(GeoServerLoader.java:309)
	at org.geoserver.config.GeoServerLoader.postProcessBeforeInitialization(GeoServerLoader.java:291)
	at org.geoserver.config.GeoServerLoaderProxy.postProcessBeforeInitialization(GeoServerLoaderProxy.java:57)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:414)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1763)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:593)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:226)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
	at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:303)
	at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:110)
	at org.springframework.beans.factory.support.ConstructorResolver.resolveConstructorArguments(ConstructorResolver.java:676)
	at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:188)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1340)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1186)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:226)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:860)
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:878)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550)
	at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:401)
	at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:292)
	at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:103)
	at org.geoserver.platform.GeoServerContextLoaderListener.contextInitialized(GeoServerContextLoaderListener.java:22)
	at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4701)
	at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5167)
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
	at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:743)
	at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:719)
	at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:705)
	at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:970)
	at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1841)
	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.geoserver.mapml.gwc.gridset.MapMLGridsets]: Constructor threw exception; nested exception is java.lang.NullPointerException
	at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:184)
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:87)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1294)
	... 107 more
Caused by: java.lang.NullPointerException
	at org.geoserver.gwc.GWC.get(GWC.java:309)
	at org.geoserver.mapml.gwc.gridset.MapMLGridsets.<init>(MapMLGridsets.java:32)
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
	at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:172)
	... 109 more
16 Jan. 15:13:19 WARN [config.GeoserverXMLResourceProvider] - Found no configuration file in config directory, will create one at 'gwc/geowebcache.xml' from template jar:file:/C:/Users/prushfor/Documents/catalina-base-2/webapps/geoserver/WEB-INF/lib/gwc-core-1.19-20210115.180523-89.jar!/geowebcache_empty.xml
16 Jan. 15:13:19 INFO [config.GeoserverXMLResourceProvider] - Found configuration file in gwc
16 Jan. 15:13:19 INFO [config.GeoserverXMLResourceProvider] - Found configuration file in gwc
16 Jan. 15:13:19 WARN [config.XMLConfiguration] - ********************************************************************************
16 Jan. 15:13:19 WARN [config.XMLConfiguration] - *** GWC configuration validation error: cvc-elt.1.a: Cannot find the declaration of element 'gwcConfiguration'.
16 Jan. 15:13:19 WARN [config.XMLConfiguration] - *** Will try to use configuration anyway. Please check the order of declared elements against the schema.
16 Jan. 15:13:19 WARN [config.XMLConfiguration] - ********************************************************************************
16 Jan. 15:13:20 INFO [config.XMLConfiguration] - Initializing GridSets from gwc
16 Jan. 15:13:20 INFO [config.XMLConfiguration] - Initializing layers from gwc
16 Jan. 15:13:21 INFO [gwc.layer] - Initializing GWC configuration based on GeoServer's Catalog
16 Jan. 15:13:21 INFO [gwc.layer] - GeoServer TileLayer store base directory is: gwc-layers
16 Jan. 15:13:21 INFO [gwc.layer] - Loading tile layers from gwc-layers
16 Jan. 15:13:21 INFO [gwc.layer] - Loaded 0 tile layers in 12.77 ms

I see above that it is not finding a geowebcache.xml and is then creating one based on an 'empty' version of that file. I created a geowebcache.xml in the MapML module that contains the definitions of my custom gridsets, but it isn't found by the system, but it seems that it used to be found (old version of geoserver.war running on another tomcat instance):

16 Jan. 16:32:56 INFO [config.GeoserverXMLResourceProvider] - Will look for 'geowebcache.xml' in directory 'C:\Users\prushfor\Downloads\apache-tomcat-8.5.54-windows-x64\apache-tomcat-8.5.54\webapps\geoserver\data\gwc'.
16 Jan. 16:32:56 INFO [config.GeoserverXMLResourceProvider] - Found configuration file in gwc
16 Jan. 16:32:56 INFO [config.GeoserverXMLResourceProvider] - Found configuration file in gwc
16 Jan. 16:32:56 INFO [config.GeoserverXMLResourceProvider] - Found configuration file in gwc
16 Jan. 16:32:56 INFO [config.XMLConfiguration] - TileLayerConfiguration file validated fine.
16 Jan. 16:32:56 INFO [config.XMLConfiguration] - Initializing GridSets from gwc
16 Jan. 16:32:56 INFO [config.XMLConfiguration] - Read GridSet APSTILE
16 Jan. 16:32:56 INFO [config.XMLConfiguration] - Read GridSet WGS84
16 Jan. 16:32:56 INFO [config.XMLConfiguration] - Read GridSet OSMTILE
16 Jan. 16:32:56 INFO [config.XMLConfiguration] - Read GridSet CBMTILE
16 Jan. 16:32:56 INFO [config.XMLConfiguration] - Initializing layers from gwc
16 Jan. 16:32:56 INFO [gwc.layer] - Initializing GWC configuration based on GeoServer's Catalog
16 Jan. 16:32:56 INFO [gwc.layer] - GeoServer TileLayer store base directory is: gwc-layers
16 Jan. 16:32:56 INFO [gwc.layer] - Loading tile layers from gwc-layers
16 Jan. 16:32:56 INFO [gwc.layer] - Loaded 33 tile layers in 49.68 ms
16 Jan. 16:32:56 INFO [storage.BlobStoreAggregator] - BlobStoreConfiguration gwc contained no blob store infos.

Any ideas much appreciated!

Implement TCRS subclass of CoordinateReferenceSystem

Background

MapML TCRS (“Tiled Coordinate Reference System”) are notionally a union of a GeoWebCache GridSet definition and a (GeoTools) projected CRS, such that each zoom level in the grid definition can be treated as derived projected CRS. In the current GeoServer MapML extension, there are four defined GridSets, named after the four TCRS defined by the MapML specification: OSMTILE, CBMTILE, WGS84, and APSTILE. Each of these defined GridSets is defined in an XML file supplied with the MapML extension. The predefined GridSets in the distributed file have parameter values defined by the MapML specification to create a GeoWebCache grid that can be used by a system administrator to configure GeoServer to serve layer content tiled by GeoWebCache as MapML responses. With the MapML extension installed, newly created (tiled) layers are automatically configured to be tiled according to these definitions by default (and thus accessible via the GeoServer WMTS interface), with the administrator having the option to remove GridSets from the layer configuration (potentially conserving tile storage resources, should they decide to serve the layer content via tiled requests). The Java implementation of TCRS in the GeoServer extension module wraps and augments a GeoTools CRS (for an underlying EPSG CRS) but does not implement any GeoTools CRS interface or class definition itself; it is a custom class otherwise unrelated to any GeoTools CRS.

Requirement

Re-define MapML TCRS as GeoTools custom projected CRS class definition, such that TCRS’ root abstract class or interface (perhaps: org.geotools.referencing.crs.TiledCoordinateReferenceSystem) defines and/or implements the “contract” of a GeoTools projected CRS, if possible. This is a preliminary essential task required to perform subsequent tasks (including making MapML available via GetMap); subsequent tasks are dependent on successful completion of this task. Document the procedure required to add additional TCRS instances as GeoTools custom projected CRS. Document the procedure required to add such GeoTools TCRS instances to the GetCapabilities response document.

Add all standard TCRS instances to the GeoServer MapML extension, so that they appear in Capabilities response documents as legal crs / srs parameter values.

The objective of the org.geotools.referencing.crs.TiledCoordinateReferenceSystem class would be to obtain the benefits of formal CRS handling with the simplicity of creating actual tile caches via the GWC API. Enable use of a TCRS to automatically define a GWC Gridset, using the enclosed tilematrixset coordinate systems definitions to create the Gridset.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.