Overview
This article describes the LuciadLightspeed WFS Server API, which provides its users with an easy framework for setting up a Web Feature Service. The WFS API provides a lot of core features out-of-the-box. The framework offers a WFS servlet complete with all required request handling facilities, GML format support, and an implementation of the OGC Filter specification.
The main configuration task that remains for the user of the API is to implement the server-side data store for the WFS. The user may choose to read geographic data from files, retrieve it from a database, or use any other method to get data.
Configuring a WFS
To get started with the configuration of a WFS, the main entry point in the API
is the class ALcdOGCWFSCommandDispatcherFactory
. This abstract class serves to initialize the WFS during server startup. You must implement the abstract methods that:
-
Set up the server-side data store
-
Determine the formats of the data that the server can send to the client
-
Initialize the filtering support
You can also override some protected methods to customize how the server handles transactions and locking. You may need to do so if a server wants to use capabilities provided by its data store to guarantee persistent and atomic updates.
The following paragraphs describe each of the command dispatcher factory methods. For implementation details, see the API reference documentation or the included samples.
Reading data
createModelDecoderFactory()
The WFS server uses the ILcdOGCModelDecoderFactory
interface to load
data. A model decoder factory uses a given data source name and returns an
ILcdModelDecoder
that can read data from that source. The command
dispatcher factory must provide a valid model decoder factory, or the
WFS won’t provide any data.
The default implementation of this method uses the service lookup mechanism
((TLcdServiceLoader)
) to pick up model decoders.
createWFSCapabilitiesProvider()
Once it has a model decoder factory, the server is ready to
load data. To tell the server which data to load, you must also implement
ILcdWFSCapabilitiesProvider
. The capabilities provider exposes a
list of feature types that the WFS offers. Each feature type
corresponds to an ILcdModel
internally. You invoke the model decoder factory to decode these models. A typical implementation of a capabilities
provider reads a list of data file names from the server configuration
files and returns those.
The list of feature types consists of ILcdWFSFeatureType
objects. An
ILcdWFSFeatureType
has the following information:
-
The name of the feature type. The name serves as the identifier of the feature type in WFS requests, and so must be unique.
-
The source name, which is used with the model decoder obtained from the model decoder factory to create an
ILcdModel
for the feature type. -
A spatial reference system (SRS) identifier, for instance an EPSG code.
-
An
ILcdOGCFeatureIDRetriever
. The feature ID retriever returns a unique identifier for every feature of the feature type in question. -
Optionally, an
ILcdBounds
, exposed using theILcdBounded
interface.
Sending data to the client
createClientModelEncoderFactory()
A WFS server responds to requests by sending geographic data back to the client.
An ILcdModelEncoder
generates that data, because it’s capable of encoding a model to the format specified by the WFS client.
The interface ILcdWFSClientModelEncoderFactory
defines the available model encoders. This factory receives the
desired output format parameter from a WFS request, and returns a corresponding ILcdWFSModelEncoder
.
By default, the WFS server uses TLcdWFSClientModelEncoderFactory
, which supports encoding a model to a
GML application schema according to GML version 2, 3.1 or 3.2. or to GeoJSON.
It’s possible to expose more output formats by implementing a custom ILcdWFSClientModelEncoderFactory
or
by extending from TLcdWFSClientModelEncoderFactory
. All output formats supported by the factory are
automatically listed in the WFS capabilities.
registerModelReferenceFormatters()
The capabilities document also specifies the SRS for every available feature
type. By default, references are formatted as an EPSG code. You can override this
behavior by registering extra
ILcdModelReferenceFormatter
implementations.
You can register more reference formatters by having the
registerModelReferenceFormatters()
method call
addModelReferenceFormatter()
for each new reference formatter you wish
to register. If more formatters are available, the server tries the last registered format first, then the next to last, and
continues until it finds a formatter
that can successfully format the model reference. If none of the
user-specified formatters are successful, the server falls back to the
default EPSG reference formatter.
Transaction processing
A request handler, created for the "Transaction"
request name, handles incoming transactions. Figure 1, “An overview of the classes involved in transaction handling.” shows how it interacts with the ALcdWFSTransactionHandler
class. It also shows how the default implementation of ALcdWFSTransactionHandler
can retrieve locked features from an ALcdWFSLock
, or unlocked features from the ILcdWFSFilteredModelFactory
. When a transaction is committed, it requests a model encoder from the ILcdWFSServerModelEncoderFactory
and saves the modified model using that encoder.
Incoming GML data is automatically decoded and converted to the original format if possible. The elements of the original
format must implement ILcdDataObject
for that, and must all have the same TLcdDataType
. The WFS-T implementation supports GML-based input formats only.
createServerModelEncoderFactory()
To support transaction handling, a Web Feature Service must be able to commit
changes to the data back to its data store. You implement this capability in the WFS Server API through the
ILcdWFSServerModelEncoderFactory
interface. This interface accepts an
ILcdModel
and returns an ILcdModelEncoder
capable of saving
this model back to its original location. If you want more control over transaction
handling, you can override the createTransactionHandlerFactory
method.
createTransactionHandlerFactory()
If you want your server to have more control over transaction handling, you may want to create
your own ALcdWFSTransactionHandler
implementation. For each transaction request
received by the server, you create an ALcdWFSTransactionHandler
instance that handles all parts of the transaction request. Once it has processed all parts of the transaction, it can be
committed.
registerModelReferenceParsers()
WFS-T transactions can provide data with custom SRS names. To support your own SRS names, you must register a parser to convert
the SRS name to an ILcdModelReference
.
You can register reference parsers in the same way as you register reference formatters. See registerModelReferenceFormatters() for a full explanation.
Filtering
createFilteredModelFactory()
A Web Feature Service supports filtering based on spatial and non-spatial
constraints. LuciadLightspeed WFS performs this filtering via the
ILcdWFSFilteredModelFactory
interface. Implementations of this
interface can take an ILcdModel
and, based on some constraints,
produce a filtered model. The contents of the filtered model are a subset of the original model.
The command dispatcher factory creates an ILcdWFSFilteredModelFactory
by calling the createFilteredModelFactory()
method. The default
implementation of ILcdWFSFilteredModelFactory
is
TLcdWFSFilteredModelFactory
. This class uses the
com.luciad.ogc.filter
package to perform filtering. For more information about using this package, see the Using OGC Filters article in the LuciadLightspeed developer’s guide.
In your applications, you can extend TLcdWFSFilteredModelFactory
and
override the createFilterEvaluator()
method to extend the filtering
support with user-defined capabilities. See the API documentation of the
com.luciad.ogc.filter
package for more details.
Locking
createLockFactory()
Web Feature Services that support transactions might also require support for locking. The default implementation locks the
features within the WFS server process. This means that other processes that might access the same data don’t see the lock.
To implement a different locking approach, you can override the createLockFactory()
method.