GeoServer REST configuration integration

GeoGig integrates well with the standard GeoServer REST configuration API in order to configure vector datastores and layers from GeoGig repositories.

You can use a combination of GeoGig’s own “Web API” and GeoServer’s REST configuration API to create a wide variety of scripts.

GeoGig’s plugin Web-API

With the GeoGig GeoServer plug-in, like with the geogig serve --multirepo command, it is possible to expose several repositories. To do so, the GeoGig plug-in installs REST entry points under the <geoserver context>/geogig/repos context (e.g. http://localhost:8080/geoserver/geogig/repos).

That root context can be used to query which repositories are being served by GeoServer.

GeoSever managed repositories are internally identified by a UUID automatically assigned when the repository is first added to the GeoServer configuration, and published through their names. The repository name is assigned by the user and must also be unique across all the configured repositories.

Each specific repository’s Web-API is accessed through the <geosever context>/geogig/repos/<repository name> entry point, a path change from when using the geogig serve command that exposes the repository at the /repos application context.

So, for example, whenever you would list the current HEAD’s commits by querying http://localhost:8182/repos/<repo name>/log if serving a single repository with geogig serve, the same command, as served by GeoServer, would be at http://localhost:8080/geoserver/geogig/repos/<repo name>/log.

From that point on, the commands available are exactly the same then when using the standalone Web API.

Plugin REST API for creating GeoGig repositories

In order to create a GeoGig Repository via the plugin’s REST API, you must send a PUT request to GeoServer that follows this URL form:

PUT http://<geoserver>/geogig/repos/<repository name>/init

Requests to the above URL will produce XML-formatted responses. If you prefer to receive JSON-formatted responses, you can send the same request to the above URL with .json appended like this:

PUT http://<geoserver>/geogig/repos/<repository name>/init.json

In both cases, <geoserver> should be replaced with the hostname and port where GeoServer is running (e.g. localhost:8080) and <repository name> should be replaced with the desired name.

Issuing a PUT request to either of the above-formatted URLs will either yield a 201 Created response, if the GeoGig Repository was created successfully, or a 409 Conflict, if the repository name specified is already in use as a GeoGig Repository name. For example, if you submit a PUT request to the following

PUT http://localhost:8080/geoserver/geogig/repos/myrepo/init

You should receive a 201 Created response with a message body like this:

<?xml version='1.0' encoding='UTF-8'?>
<response>
    <success>true</success>
    <repo>
        <name>myrepo</name>
        <atom:link xmlns:atom="http://www.w3.org/2005/Atom" rel="alternate" href="http://localhost:8080/geoserver/geogig/repos/myrepo.xml" type="application/xml"/>
    </repo>
</response>

If myrepo already existed, you would receive a 409 Conflict response with a message body like this:

<?xml version='1.0' encoding='UTF-8'?>
<response>
    <success>false</success>
    <error>Cannot run init on an already initialized repository.</error>
</response>

If you submit a PUT request and want a JSON response, the above example changes to this:

PUT http://localhost:8080/geoserver/geogig/repos/myrepo/init.json

And a success response would look like this:

{
  "response": {
    "success": true,
    "repo": {
      "name": "myrepo",
      "href": "http://localhost:8080/geoserver/geogig/repos/myrepo.json"
    }
  }
}

Or, if myrepo already existed:

{
  "response": {
    "success": false,
    "error": "Cannot run init on an already initialized repository."
  }
}

If the PUT is successful, GeoServer should now contain a new GeoGig repository named myrepo

../_images/geoserver-api-create-repo.png

Newly created GeoGig repository

If you notice in the figure above, creating a repository in this manner will create the repository in a sub-directory of the GeoGig config directory of GeoServer (in this case, /opt/geoserver/2.9/data_dir/geogig/config/). While this is fine, it may not be desirable to have the repository in the GeoGig config directory. Also, if you do not provide additional request parameters, the repository will not have config parameters set for user.name or user.email, which are required to be set (globally or locally) before you will be able to commit changes to the repository. Lastly, you cannot create a GeoGig repository that is backed by PostgreSQL by only providing the repository name in the PUT. See Creating a GeoGig repository in a specific parent directory in order to create a Directory-backed GeoGig repository in a specific parent directory or Creating a GeoGig repository backed by PostgreSQL to create a PostgreSQL-backed GeoGig Repository.

Creating a GeoGig repository in a specific parent directory

If you wish to create a GeoGig repository in a location other than GeoServer’s config directory for GeoGig, you must send the parentDirectory parameter in the PUT request, telling the plugin in which directory to create the repository. You can provide this parameter in one of two ways.

1. Specify the parentDirectory, authorName and authorEmail as a URL-encoded form parameter, e.g.:

curl -X PUT -H "Content-Type: application/x-www-form-urlencoded" -d 'parentDirectory=/opt/geogig/repos&authorName=geogig&authorEmail=geogig@geogig.org' "http://localhost:8080/geoserver/geogig/repos/myrepo/init"

2. Specify the parentDirectory, authorName and authorEmail as a JSON object, e.g.:

curl -X PUT -H "Content-Type: application/json" -d '{
        "parentDirectory": "/opt/geogig/repos",
        "authorName": "geogig",
        "authorEmail": "geogig@geogig.org"
    }' "http://localhost:8080/geoserver/geogig/repos/myrepo/init"

With either form, you must ensure that the PUT request has the correct Content-Type encoded into the request header. If you don’t put the correct Content-Type in the header, the plugin will not correctly parse the request.

Also, as stated in the previous section, you can request a JSON-formatted response by appending .json to the PUT URL.

Creating a GeoGig repository backed by PostgreSQL

If you wish to create a GeoGig repository that is backed by a PostgreSQL database, you must send the PostgreSQL connection parameters in a similar manner, as above. Again, you may send the parameters as a URL-encoded form, or as a JSON Object.

PostgreSQL connection parameters (* indicates a required field)

Parameter Default Description
dbName (*)   Name of the PostgreSQL database to connect to
dbPassword (*)   Password of the database user with which to connect
dbHost “localhost” Hostname of the PostgreSQL database server to connect to
dbPort “5432” Port the database is listening on
dbSchema “public” Database schema to connect to
dbUser “postgres” Username to connect with
authorName   Committer name for the repository
authorEmail   Committer email for the repository

From the table above, you’ll see that you must provide at least dbName and dbPassword. Though not required, there are no default values for authorName or authorEmail. It is highly recommended that you specify these in an INIT request. Defaults will be used for the remaining parameters, if not specified. Parameters can be specified as a URL-encoded form or as a JSON object.

1. URL-encoded form:

curl -X PUT -H "Content-Type: application/x-www-form-urlencoded" -d 'dbHost=localhost&dbPort=5432&dbName=repos&dbSchema=public&dbUser=geogig&dbPassword=geogig&authorName=geogig&authorEmail=geogig@geogig.org' "http://localhost:8080/geoserver/geogig/repos/myrepo/init"

2. JSON Object:

curl -X PUT -H "Content-Type: application/json" -d '{
        "dbHost": "localhost",
        "dbPort": "5432",
        "dbName": "repos",
        "dbSchema": "public",
        "dbUser": "geogig",
        "dbPassword": "geogig",
        "authorName": "geogig",
        "authorEmail": "geogig@geogig.org"
    }' "http://localhost:8080/geoserver/geogig/repos/myrepo/init"

Again, the Content-Type must be set correctly for the plugin to parse the connection parameters and you may request a JSON-formatted response by appending .json to the PUT URL.

Creating a GeoGig datastore with REST

To create a GeoGig datastore through the GeoServer REST API, you must already have a GeoGig repository configured in GeoServer. See Plugin REST API for creating GeoGig repositories for creating a GeoGig Repository in GeoServer.

Once you have a GeoGig repository, you need only follow the standard procedure, knowing which datastore connection parameters to use.

That is, issuing a POST request to /workspaces/<ws>/datastores[.<format>], where the request body for the XML representation appears:

<dataStore>
   <name>${datastore name}</name>
   <connectionParameters>
      <entry key="geogig_repository">${repository URI}</entry>
      <entry key="branch">${branch}</entry>
   </connectionParameters>
</dataStore>

That’s all the information needed to create a GeoGig datastore.

  • ${datastore name} is the name to be given to the datastore, which then will be accessible through /workspaces/<ws>/datastores/<datastore name>.
  • ${repository URI} is a GeoServer URI string that identifies the GeoGig repository in GeoServer. It should be in the form geoserver://<repository name>
  • ${branch} is optional and represents the name of the branch the datastore is going to serve its data from. If not provided, the datastore will use whichever is the currently checked out branch in the repository each time it (or the datastore) is accessed.

Quick example:

For the impatient, here’s a very quick cheat sheet on how to create a datastore and layer for a repository.

Suppose you have a repository named myrepo in GeoServer, it contains a roads feature type tree, and GeoServer has a workspace named ws1:

curl -v -u admin:geoserver -XPOST -H "Content-type: text/xml" -d "<dataStore><name>my_geogig_repo</name><connectionParameters><entry key=\"geogig_repository\">geoserver://myrepo</entry></connectionParameters></dataStore>" http://localhost:8080/geoserver/rest/workspaces/ws1/datastores
< HTTP/1.1 201 Created
$ curl -v -u admin:geoserver -XPOST -H "Content-type: text/xml" -d "<featureType><name>roads</name></featureType>" http://localhost:8080/geoserver/rest/workspaces/ws1/datastores/my_geogig_repo/featuretypes
< HTTP/1.1 201 Created

For a more thorough example take a look at the tutorial below.

cURL tutorial

The following is a short tutorial on how to use a combination of GeoGig and GeoServer web APIs to configure datastores and layers from a GeoGig repository.

Lets start by listing the available repositories, given there are none yet added to GeoServer:

$ curl -v -u admin:geoserver -H "Accept:text/xml" "http://localhost:8080/geoserver/geogig/repos"
< HTTP/1.1 200 OK
< Content-Type: application/xml
<?xml version='1.0' encoding='UTF-8'?>
<repos/>

We got an empty list of repositories.

Now lets create an empty repository in GeoServer. Follow one of the procedures here or here.

Now lets create a workspace in GeoServer to hold our datastore:

$ curl -v -u admin:geoserver -XPOST -H "Content-type: text/xml" -d "<workspace><name>geogigtest</name></workspace>" http://localhost:8080/geoserver/rest/workspaces
> POST /geoserver/rest/workspaces HTTP/1.1
< HTTP/1.1 201 Created

Note

Beware of not calling your namespace geogig as it’s “local workspace catalog” entry point will conflict with the /geogig REST API entry point.

Create a GeoGig datastore called geogig_datastore_test inside that workspace. To do so, create a file named datastore.xml in the current directory with the following content (note the value of the geogig_repository connection parameter is the repository directory):

<dataStore>
   <name>geogig_datastore_test</name>
   <connectionParameters>
      <entry key="geogig_repository">geoserver://myrepo</entry>
   </connectionParameters>
</dataStore>

The run:

$ curl -v -u admin:geoserver -XPOST -H "Content-type: text/xml" -T datastore.xml http://localhost:8080/geoserver/rest/workspaces/geogigtest/datastores
< HTTP/1.1 201 Created

And verify the datastore exists:

$ curl -v -u admin:geoserver -XGET -H "Accept: text/xml" http://localhost:8080/geoserver/rest/workspaces/geogigtest/datastores/geogig_datastore_test
< HTTP/1.1 200 OK
< Content-Type: application/xml
<dataStore>
  <name>geogig_datastore_test</name>
  <type>GeoGIG</type>
  <enabled>true</enabled>
  <workspace>
    <name>geogigtest</name>
    <atom:link xmlns:atom="http://www.w3.org/2005/Atom" rel="alternate" href="http://localhost:8080/geoserver/rest/workspaces/geogigtest.xml" type="application/xml"/>
  </workspace>
  <connectionParameters>
    <entry key="geogig_repository">geoserver://myrepo</entry>
    <entry key="namespace">http://geogigtest</entry>
  </connectionParameters>
  <__default>false</__default>
  <featureTypes>
    <atom:link xmlns:atom="http://www.w3.org/2005/Atom" rel="alternate" href="http://localhost:8080/geoserver/rest/workspaces/geogigtest/datastores/geogig_datastore_test/featuretypes.xml" type="application/xml"/>
  </featureTypes>
</dataStore>

Now, let’s import some data. For this example, we are importing a ZIP of a Shapefile called railways.zip that is located in the current working directory:

$ curl -v -u admin:geoserver -XPUT -H "Content-type: application/zip" --data-binary @railways.zip http://localhost:8080/geoserver/rest/workspaces/geogigtest/datastores/geogig_datastore_test/file.shp

You can create a second datastore for the same repository using the repository and different branch. To verify, let’s create a branch in the repository, and a new datastore that uses that branch, instead. To do so, copy the following XML fragment to a file called datastore_branch.xml. This fragment has a different name, an extra branch connection parameter, and the same repository directory:

<dataStore>
<name>experimental</name>
<connectionParameters>
   <entry key="geogig_repository">geoserver://myrepo</entry>
   <entry key="branch">experimental</entry>
</connectionParameters>
</dataStore>

Then create the branch called experimental in the repository:

$ curl -v -u admin:geoserver -XGET http://localhost:8080/geoserver/geogig/repos/myrepo/branch?branchName=experimental

Then call the GeoServer REST API to create the new datastore:

$ curl -v -u admin:geoserver -XPOST -H "Content-type: text/xml" -T datastore_branch.xml http://localhost:8080/geoserver/rest/workspaces/geogigtest/datastores
< HTTP/1.1 201 Created

Finally get the new repository information:

$ curl -u admin:geoserver -XGET -H "Accept: text/xml" http://localhost:8080/geoserver/rest/workspaces/geogigtest/datastores/experimental
<dataStore>
  <name>experimental</name>
  <type>GeoGIG</type>
  <enabled>true</enabled>
  <workspace>
    <name>geogigtest</name>
    <atom:link xmlns:atom="http://www.w3.org/2005/Atom" rel="alternate" href="http://localhost:8080/geoserver/rest/workspaces/geogigtest.xml" type="application/xml"/>
  </workspace>
  <connectionParameters>
    <entry key="geogig_repository">geoserver://myrepo</entry>
    <entry key="namespace">http://geogigtest</entry>
    <entry key="branch">experimental</entry>
  </connectionParameters>
  <__default>false</__default>
  <featureTypes>
    <atom:link xmlns:atom="http://www.w3.org/2005/Atom" rel="alternate" href="http://localhost:8080/geoserver/rest/workspaces/geogigtest/datastores/experimental/featuretypes.xml" type="application/xml"/>
  </featureTypes>
</dataStore>

Now you have two different datastores, served from the same GeoGig repository, at different branches. These two different branches may have different feature type trees (i.e. “layers”) or different versions of the same.

Let’s revisit the initial query in this tutorial and check the list of available repositories using GeoGig’s own REST API:

$ curl -v -u admin:geoserver -H "Accept:text/xml" "http://localhost:8080/geoserver/geogig/repos"
< HTTP/1.1 200 OK
<?xml version="1.0" encoding="UTF-8"?>
<repos>
  <repo>
    <id>bc1b0904-d43b-4871-aaad-450f1a577d15</id>
    <name>myrepo</name>
    <atom:link xmlns:atom="http://www.w3.org/2005/Atom" rel="alternate" href="http://localhost:8080/geoserver/geogig/repos/myrepo.xml" type="application/xml"/>
  </repo>
</repos>
$ curl -v -u admin:geoserver -H "Accept:text/xml" "http://localhost:8080/geoserver/geogig/repos/myrepo.xml"
< HTTP/1.1 200 OK
<?xml version='1.0' encoding='UTF-8'?>
<repository>
   <id>bc1b0904-d43b-4871-aaad-450f1a577d15</id>
   <name>myrepo</name>
   <location>file:/opt/geogig/repos/3d54eb66-805f-4fd1-b60a-c3831b5f3765/</location>
</repository>

Also make sure the repository contains the expected feature type trees using the ls-tree command:

$ curl -v -u admin:geoserver -H "Accept:application/xml" "http://localhost:8080/geoserver/geogig/repos/myrepo/ls-tree"
< HTTP/1.1 200 OK
<response>
   <success>true</success>
   <node><path>railways</path></node>
</response>

Finally, let’s query the layer for the railways feature type (it was created when we imported the shapefile ZIP above):

$ curl -u admin:geoserver -XGET -H "Accept: text/xml" http://localhost:8080/geoserver/rest/layers
<layers>
  ....
  <layer>
    <name>railways</name>
    <atom:link xmlns:atom="http://www.w3.org/2005/Atom" rel="alternate" href="http://localhost:8080/geoserver/rest/layers/railways.xml" type="application/xml"/>
  </layer>
</layers>

Changing the configuration of either the feature types or the layers is just a matter of utilizing the usual GeoServer REST API to do so. See Feature types and Layers in the GeoServer user manual for more information. The GeoServer cURL examples are also a good source of information.

back to top