Practical Experience with GeoServer

http://docs.geoserver.org

http://suite.opengeo.org/opengeo-docs/

Data Hierarchy

Workspace

Data Store

Layer

Workspace

  • Container used to group similar layers together
  • Name - unique identifier 
  • Namespace URI - an identifier describing the project

Data Store

  • Source for the data served out by Geoserver
  • Divided into Vector and Raster sources
  • Namespace URI - an identifier describing the project
  • Plugins expand the range of available datasources

Layer

  •  Geographic datasets from the datastore

Importing Layers

  • One at a time

Importing Layers

  • One at a time
  • Batch and Automated

Importer 

  • Plugin 
  • Useful for importing a small number of layers

GeoServer RESTful  API

  • GeoServer provides a RESTful interface for reading and writing configuration information
  • API can be accessed in a variety of ways

cURL

curl -v -u admin:geoserver -XPOST -H "Content-type: text/xml"
  -d "<workspace><name>acme</name></workspace>"
  http://localhost:8080/geoserver/rest/workspaces

Python

from geoserver.catalog import Catalog
cat = Catalog("http://localhost:8080/geoserver/")
topp = self.cat.get_workspace("topp")
shapefile_plus_sidecars = shapefile_and_friends("states")
# shapefile_and_friends should look on the filesystem to find a shapefile
# and related files based on the base path passed in
#
# shapefile_plus_sidecars == {
#    'shp': 'states.shp',
#    'shx': 'states.shx',
#    'prj': 'states.prj',
#    'dbf': 'states.dbf'
# }

# 'data' is required (there may be a 'schema' alternative later, for creating empty featuretypes)
# 'workspace' is optional (GeoServer's default workspace is used by... default)
# 'name' is required
ft = self.cat.create_featuretype(name, workspace=topp, data=shapefile_plus_sidecars)
  • gsconfig library from Boundless
  • https://github.com/boundlessgeo/gsconfig

Ruby

$ rake console
> require 'rgeoserver'
> catalog = RGeoServer::Catalog.new
 => Catalog: http://localhost:8080/geoserver/rest
> w = catalog.get_default_workspace
=> RGeoServer::Workspace: topp
> ds = w.data_stores.first
=> RGeoServer::DataStore: states_shapefile
> ds.profile
=> {"name"=>"states_shapefile", 
    "enabled"=>"true", 
    "connectionParameters"=>{
      "url"=>"file:data/shapefiles/states.shp", 
      "namespace"=>"http://www.openplans.org/topp"}, 
    "featureTypes"=>["states"]} 
> ft = ds.featuretypes.first
=> RGeoServer::FeatureType: states 
> ft.profile
=> {:name=>"states", :workspace=>"topp", :nativeName=>"states"}  

> lyr = RGeoServer::Layer.new c, :name => 'Arc_Sample'
=> RGeoServer::Layer: Arc_Sample 
> lyr.profile
=> {"name"=>"Arc_Sample", 
    "path"=>"/", 
    "defaultstyle"=>"rain", 
    "styles"=>["raster"], 
    "type"=>"RASTER", 
    "enabled"=>"true", 
    "attribution"=>{"logoWidth"=>"0", "logoHeight"=>"0"}, 
    "resource"=>{
      "type"=>"coverage", 
      "name"=>"Arc_Sample", 
      "store"=>"arcGridSample", 
      "workspace"=>"nurc"},
    "metadata"=>{
      "GWC.autoCacheStyles"=>"true", 
      "GWC.metaTilingX"=>"4", 
      "GWC.metaTilingY"=>"4", 
      "GWC.gutter"=>"0", 
      "GWC.cachedNonDefaultStyles"=>"raster", 
      "GWC.enabled"=>"true", 
      "GWC.cacheFormats"=>"image/jpeg,image/png", 
      "GWC.gridSets"=>"EPSG:4326,EPSG:900913"}}
> sld = lyr.styles.first
=> RGeoServer::Style: raster 
> sld.profile
=> {"name"=>"raster", 
    "sld_version"=>"1.0.0", 
    "filename"=>"raster.sld", 
    "sld"=>{"sld_name"=>"raster", "sld_title"=>"Default Raster"}}
  • rgeoserver library from Stanford
  • https://github.com/sul-dlss/rgeoserver

Java

        final GSCoverageEncoder encoder=new GSImageMosaicEncoder();

        //add a name to the coverage
        encoder.setName("coverageName");
        encoder.setSRS(srs);

        encoder.addKeyword("KEYWORD_1");
        encoder.addKeyword("KEYWORD_2");
        encoder.addKeyword("...");
        encoder.addKeyword("KEYWORD_N");

        //add an active (true) dimension
        final GSDimensionInfoEncoder dim=new GSDimensionInfoEncoder(true);
        //add presentation dimension
        dim.setPresentation( Presentation.CONTINUOUS_INTERVAL);
        //add dimension to the coverage as time
        encoder.setMetadata("time", dim);

        final GSDimensionInfoEncoder dim2=new GSDimensionInfoEncoder(true);
        dim2.setPresentation( Presentation.LIST);
        encoder.setMetadata("elevation", dim2);

        encoder.setLatLonBoundingBox(minx, miny, maxx, maxy, crs);

        GSResourceEncoder coverageEncoder = new GSCoverageEncoder();

        GSLayerEncoder layerEncoder = new GSLayerEncoder();
        layerEncoder.setDefaultStyle(defaultStyle);

        publishExternalMosaic(workspace, storeName, mosaicDir, encoder, layerEncoder);
  • geoserver-manager from GeoSolutions
  • https://github.com/geosolutions-it/geoserver-manager

Opinions

Start with cURL examples to get a feel for the API

curl -v -u admin:geoserver -XGET -H "Accept: text/xml"
  http://localhost:8080/geoserver/rest/workspaces/acme
<workspace>
  <name>acme</name>
  <dataStores>
    <atom:link xmlns:atom="http://www.w3.org/2005/Atom" rel="alternate"
     href="http://localhost:8080/geoserver/rest/workspaces/acme/datastores.xml"
     type="application/xml"/>
  </dataStores>
  <coverageStores>
    <atom:link xmlns:atom="http://www.w3.org/2005/Atom" rel="alternate"
     href="http://localhost:8080/geoserver/rest/workspaces/acme/coveragestores.xml"
     type="application/xml"/>
  </coverageStores>
  <wmsStores>
    <atom:link xmlns:atom="http://www.w3.org/2005/Atom" rel="alternate"
     href="http://localhost:8080/geoserver/rest/workspaces/acme/wmsstores.xml"
     type="application/xml"/>
  </wmsStores>
</workspace>

For bulk uploading, you can build simple python scripts with the requests library

for key in layers_data:
  path = DATASTORE + layers_data[key] + '/geoblacklight.xml'
  headers = {'content-type': 'application/json'}

  try:
	counter += 1
	print str(counter) + ' / ' + str(total_records) + '    ' + layers_data[key]
	files = {'file': ('geoblacklight.xml', open(path, 'rb'), 'application/xml', \
		{'Expires': '0'})}
	r = requests.post(SOLR_URL, files=files )
	
	# commit every 100 docs
	if counter % 100 == 0:
		r = requests.get(SOLR_COMMIT_URL)
	
  except:
	print 'Error: ' + key
import requests

Administration

System Architecture

  • Clustering
  • Failover
  • High availability
  • Performance tweaks

http://boundlessgeo.com/whitepaper/geoserver-production-2/

JDBCConfig

  • Make use of the JDBCConfig module
  • Stores the catalog configuration in a database rather than on the file system

Security

  • Connecting to local authentication systems
  • Authorization for admin access
  • Workspace and service level authorization

Caching

  • GeoWebCache tile caches for increased performance
Made with Slides.com