[FrontPage] [TitleIndex] [WordIndex

Implementing an OGC Webservice with deegree 3

This document will try to give an overview of the steps necessary to implement an OGC-Webservice specification with deegree3. Since there is no 'perfect' solution for a specific implementation, only hints and pointing directions will be given.

1. Overview - The OGCFrontController

All OGC services are based upon the http protocol. The http protocol defines a set of operations of which (at the moment) only GET and POST are used. These operations are used to send an OGC request to your service. At the moment three different the request encoding are standardized by the OGC:

This is why, the OGCFrontcontroller (defined in the services module) delegates all incoming requests (GET-POST) to one of three methods, doKVP, doXML, doSOAP, which your service controller should implement.

But how is my ServiceController called? I hear you think. This will be described in just a minute, for now just assume it will be called.

Delegating incoming requests is not the only thing the OGCFrontcontroller does, it is able to load your service configuration, resolve file locations and extract files from multi part mime messages.

1.1. Validation and identification of dependencies for XML/XSD-documents

This paragraph contains some useful information about how to recognize dependencies inside the xml-docs and their schemas if you need to read the specification later... Eclipse is a good for-free-tool to handle this fast and easy. At the opengis-site you can find the SCHEMAS_OPENGIS_NET file. If you download and unpack it go into eclipse and create a new Project -> Example and take Editing and validating XML files -> press Next and finish this process. After that just import the unpacked filesystem. Now you can browse between the xsd-files supported from the ogc.

2. Service Controller specifics

Since the OGCFrontcontroller should be able to delegate an incoming (http) request to your ServiceController, you need to make it aware of the operation names you are capable of( or interested in), as well as the namespaces of incoming xml requests (if the ogc-standard was not defined using a DTD).

If an incoming request meets one of the supplied criteria (an operationname or a namespace) it will call one of the appropriate methods:

These methods are defined in the abstract class org.deegree.services.controller.AbstractOGCServiceController, which is why your ServiceController should always extend this class. You should implement the init-method to run the stuff, which has the following minimal declaration:

public void init( XMLAdapter controllerConf,DeegreeServicesMetadata serviceMetadata ) throws ControllerInitException {
  init( serviceMetadata, your_Implementation_of_IMPLEMENTATION_METADATA );
  //other stuff to initialize
}

2.1. Implementation meta data

As you can see in the above code, each service should implement it's own definition of org.deegree.services.controller.ImplementationMetadata. This information is needed by the OGCFrontcontroller to correctly delegate any incoming request, your implementation should at least give following information

to put it all together you should specify something like the code below. The example was copied from the WPVS (Web Perspective View Service) specification implementation (in the core module: org.deegree.protocol.wpvs). You should use the appropriate abbreviation of your OGC Webservice:

public class WPVSConstants {

  /** Namespace for elements from the WPVS specification */
  public static final String WPVS_NS = "http://www.opengis.net/wpvs/1.0.0";

  /** WPVS protocol version 1.0.0 */
  public static final Version VERSION_100 = Version.parseVersion( "1.0.0" );

  public enum WPVSRequest {
    /**
    * Each service should implement the GetCapabilities
    */
    GetCapabilities,
    /**
    * An operation of the WPVS
    */
    GetView,
    /**
    * The GetDescription operation allows clients to retrieve the descriptions of one or more identified datasets
    * or styles.
    */
    GetDescription,
    /**
    * The GetLegendGraphic operation allows a client to retrieve a graphic containing a map legend for an
    * identified dataset and style.
    */
    GetLegendGraphic
  }
}

For your service you can specify dummy values. In your ServiceController you should implement the IMPLEMENTATION_METADATA, where [VERSION] is the configured version you are implementing in (by dev_convention stable releases are even numbers, unstable releases are odd numbers).

/**
* Defines all metadata for this service
**/
private static final ImplementationMetadata<WPVSRequestType> IMPLEMENTATION_METADATA =
                     new ImplementationMetadata<WPVSRequestType>() {
  {
    supportedVersions = new Version[] { VERSION_100 };
    handledNamespaces = new String[] { WPVS_NS };
    handledRequests = WPVSRequestType.class;
    supportedConfigVersions = new Version[] { Version.parseVersion( "[VERSION]" ) };
  }
};

2.2. Configuring a WebService

You now have the minimal requirements to run a service, well... almost anyway. There is still the configuration of the service to attend to.

One of the concepts of deegree3 is the separation of the service framework API and the OGC protocol API. In theory (maybe in practice as well) this separation of concerns allows for the reusing of the framework api although the protocol is unstable and changes in different specification versions (change are relatively frequent in the OGC world). Hence a better abstraction of the protocol is guaranteed.

(Just keep in mind this paragraph) This means you are going to have to extract all OGC specific specification details into the controller level (org.deegree.services.controller) and do the service specific operations (e.g draw a map for the WMS) in the service level (org.deegree.services).

As a result of the above concept, all services should be defined in two different xsd files. You are going to have to create yourself:

  1. The information of the OCG protocol of the service, the OGC_ABBREV_published_information.xsd
  2. The configuration of the framework side of the service, the OGC_ABBREV_service_configuration.xsd

The services_metadata.xsd file is located in d3_services/resources/schemas/webservices/VERSION/services_metadata.xsd. This file defines elements for supplying information for all deployed service. The idea here is, that in a standard deployment container the service provider information is valid for all services and thus only need to be added once.

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:wpvs="http://www.deegree.org/services/wpvs"
 <!-- and other Namespaces ...please have a look at the other services -->
           elementFormDefault="qualified" jaxb:version="2.1">
 <xs:import namespace="http://www.deegree.org/datasource"
            schemaLocation="../../../../../d3_core/resources/schema/datasource/0.1.0/all_datasources.xsd"/>
 <!-- here you see the configured version (0.1.0)-->
 <xs:import namespace="http://www.deegree.org/commons"
            schemaLocation="../../../../../d3_core/resources/schema/commons/0.1.0/commons.xsd"/>
 <xs:annotation>
  <xs:appinfo>
   <jaxb:schemaBindings>
    <jaxb:package name="org.deegree.services.wpvs.configuration"/>
   </jaxb:schemaBindings>
  </xs:appinfo>
 </xs:annotation>
 <xs:element name="ServiceConfiguration">
  <xs:annotation>
   <xs:documentation>
        Top root element of the service configuration, it defines rendering parameters,
        get view request restrictions as well as datasets and elevation models.
      </xs:documentation>
  </xs:annotation>
  <xs:complexType>
   <xs:sequence>
    <!-- maximum view width that can be requested. default = 1200 -->
    <xs:element name="MaxViewWidth" type="xs:int" default="1200" minOccurs="0"/>
    <!-- maximum view height that can be requested. default = 1000 -->
    <xs:element name="MaxViewHeight" type="xs:int" default="1000" minOccurs="0"/>
   </xs:sequence>
  </xs:complexType>
   <!-- ... -->
 </xs:element>
</xs:schema>

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:wpvs="http://www.deegree.org/services/wpvs"
 <!--  and other Namespaces ...please have a look at the other services -->
 elementFormDefault="qualified" attributeFormDefault="unqualified" jaxb:version="2.1">
 <xs:annotation>
  <xs:appinfo>
   <jaxb:schemaBindings>
    <jaxb:package name="org.deegree.services.controller.wpvs.configuration"/>
   </jaxb:schemaBindings>
  </xs:appinfo>
 </xs:annotation>
 <xs:import namespace="http://www.deegree.org/webservices"
            schemaLocation="../../webservices/0.1.0/services_metadata.xsd"/>
 <xs:import namespace="http://www.deegree.org/commons"
            schemaLocation="../../../../../d3_core/resources/schema/commons/0.1.0/commons.xsd"/>
 <xs:element name="PublishedInformation">
  <xs:complexType>
   <xs:sequence>
    <xs:element name="AllowedOperations">
     <xs:complexType>
      <xs:sequence>
       <xs:element name="GetCapabilities">
        <xs:complexType/>
       </xs:element>
        <!--and more Ops actually-->
      </xs:sequence>
     </xs:complexType>
    </xs:element>
   </xs:sequence>
  </xs:complexType>
 </xs:element>
</xs:schema>

Because of the separation of configurations, it might --in a worse case scenario-- be necessary to edit 2*n files for n services. This is why all services actually become one xml instance file (yeah it's is kind of confusing), in which these two elements can (or should) be defined. To make it even more user friendly (and because of binding issues) you should create one more xsd file defining these two elements as optional elements like this (taken from the WPVS):

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:wpvs="http://www.deegree.org/schemas/services/wpvs"
 xmlns:xs="http://www.w3.org/2001/XMLSchema"
 targetNamespace="http://www.deegree.org/schemas/services/wpvs"
 elementFormDefault="qualified">
 <xs:include schemaLocation="wpvs_published_information.xsd"/>
 <xs:include schemaLocation="wpvs_service_configuration.xsd"/>
 <xs:element name="deegreeWPVS">
  <xs:complexType>
   <xs:annotation>
    <xs:documentation>Groups the two configuration elements into one root element.</xs:documentation>
   </xs:annotation>
   <xs:sequence>
    <!-- Top element of the configuration of the service -->
    <xs:element ref="wpvs:ServiceConfiguration"/>
    <!-- Top element of the protocol configuration -->
    <xs:element ref="wpvs:PublishedInformation" minOccurs="0"/>
   </xs:sequence>
   <xs:attribute name="configVersion" use="required" fixed="0.1.0"/>
  </xs:complexType>
 </xs:element>
</xs:schema>

After you've successfully created the above xsd files (and they are valid) you must bind them with jaxb (Java Api for XML Binding). After some considerations, we've chosen JAXB for this purpose. This process is shown in the code, already:

<jaxb:schemaBindings>
  <jaxb:package name="org.deegree.services.controller.wpvs.configuration"/>
</jaxb:schemaBindings>

2.3. Binding the Schema files

Todo this binding, you can use the mechanism supplied in the d3_services/build/bind-config-targets.xml file. If you take a look at this file, you'll find that different targets with signature

<target name="bind-OGC_ABBREV-conf"/>

are already defined. You may want to copy such a target, replace the OGC_ABBREV and the value.

<target name="bind-wpvs-config" description="Bind the wpvs configuration files and publish the result.">
  <property name="service.name" value="wpvs" />
  <antcall target="bind-service" />
</target>

Now you should create a template in d3_services/build/webapp-targets.xml

<target name="create-wpvs-template" description="populates the webapp directory with wpvs files">
  <property name="service.name" value="wpvs" />
  <antcall target="service-template-no-generic-client" />
</target>

After you've copied the ant targets you are free to take-off. Open a command line (a shell) and goto the d3_service directory. Type

ant -f scripts/build/bind-[OGC_ABBREV]-config

and you should see something like this:

Buildfile: scripts/build/bind-config-targets.xml

bind-wpvs-config:

create-xjc-task:

bind-general:
      [xjc] Compiling file:/home/user/workspace/d3_services/resources/schema/wpvs/0.1.0/wpvs_service_configuration.xsd
      [xjc] removing old output files
      [xjc] Writing output to /home/user/workspace/d3_services/src

bind-publish-information:

create-xjc-task:

bind-general:
      [xjc] Compiling file:/home/user/workspace/d3_services/resources/schema/wpvs/0.1.0/wpvs_published_information.xsd
      [xjc] removing old output files
      [xjc] Writing output to /home/user/workspace/d3_services/src

BUILD SUCCESSFUL
Total time: 9 seconds

There are some more information in the output...but that's the relevant issue. After that you can build the webservice, shown in buildingDeegree3WithAnt section 3.

3. Abstraction of Service operations


CategoryDeegree3


2018-04-20 12:05