[Geoserver-devel] a plan for wfs 2.0

Hi all,

As many of you know we have managed to find funding for wfs 2.0 in geoserver. Work has commenced and I wanted to run a few high level architecture decisions by the group for feedback.

When it comes to ows services (with multiple versions) in geoserver there are two ends of a spectrum. One end is that the two service versions are relatively similar and not much changes. The other end is that the two are radically different. An example of the former is wfs 1.0 → 1.1. An example of the latter is wcs 1.0 → wcs 1.1.

Now… wfs 1.1 → 2.0 is somewhat in the middle of the spectrum. The changes are significant but the core of the service is still relatively the same. The degree of changes impacts a number of decisions, the first one we run up against is the request object model to use. For instance, since wfs 1.0 and 1.1 were so much the same we just generated an object model based on the wfs 1.1 schema, and had both service versions us that. But for wcs the schemas were just too radically different so each service has its own object model.

Looking over the spec I think that the changes in wfs 2.0 are enough to warrant its own object model. Which brings up a problem. The existing wfs operations (which have a lot of logic we need to reuse) are written against the old model. The solution I have come up with thus far is to create a level of indirection between the request object model and the operations that use them. This level of indirection, which i am calling RequestObjectHandler, basically encapsulates the details of accessing the object model with an implementation for the 1.0/1.1 model and an implementation for the 2.0 model.

My first cut at this class can be found here:

https://github.com/jdeolive/geoserver/blob/wfs2/wfs/src/main/java/org/geoserver/wfs/RequestObjectHandler.java

And if you look at say one of the operation classes, like GetFeature, it now has an additional constructor to take an instance of the request object handler.

https://github.com/jdeolive/geoserver/blob/wfs2/wfs/src/main/java/org/geoserver/wfs/GetFeature.java

Thoughts and feedback or an alterative approach are all welcome. Having to access all request object properties through the handler is somewhat tedious… but seemed like a better approach then trying to duplicate or refactor the operation classes.

-Justin


Justin Deoliveira
OpenGeo - http://opengeo.org
Enterprise support for open source geospatial.

Couple questions inline…

As many of you know we have managed to find funding for wfs 2.0 in geoserver. Work has commenced and I wanted to run a few high level architecture decisions by the group for feedback.

Congrats on the work :slight_smile:

Looking over the spec I think that the changes in wfs 2.0 are enough to warrant its own object model. Which brings up a problem. The existing wfs operations (which have a lot of logic we need to reuse) are written against the old model. The solution I have come up with thus far is to create a level of indirection between the request object model and the operations that use them. This level of indirection, which i am calling RequestObjectHandler, basically encapsulates the details of accessing the object model with an implementation for the 1.0/1.1 model and an implementation for the 2.0 model.

Okay I can see what you are doing; I like the clean separation between the information present in the provided request; and clear adapting code to translate that for the GetFeature operation.

My first cut at this class can be found here:

https://github.com/jdeolive/geoserver/blob/wfs2/wfs/src/main/java/org/geoserver/wfs/RequestObjectHandler.java

And if you look at say one of the operation classes, like GetFeature, it now has an additional constructor to take an instance of the request object handler.

https://github.com/jdeolive/geoserver/blob/wfs2/wfs/src/main/java/org/geoserver/wfs/GetFeature.java

Thoughts and feedback or an alterative approach are all welcome. Having to access all request object properties through the handler is somewhat tedious… but seemed like a better approach then trying to duplicate or refactor the operation classes.

So it seems to come down to this:


    public static RequestObjectHandler get(Object request) {
        EObject eobj = (EObject) request;
        if (eobj.eClass().getEPackage() instanceof Wfs20Package) {
            return new WFS_20();
        }
        return new WFS_11();

The use of the word “handler” still throws mefor a bit of a loop as I am used to the “event–>handler” setup and geoserver runs “request -> operation → response”.

Q: Would RequestAdapter be out of line? A: Yes as it does not actually hold on to the request; each method just does the conversion work.

So it is a strategy; isolating the code required to pull the needed information out of a protocol specific request for the GetFeature code.

So big +1 on the approach; but then again I usually like your lack of duplication in your designs.


Jody Garnett

On Tue, May 3, 2011 at 7:24 PM, Justin Deoliveira <jdeolive@anonymised.com> wrote:

My first cut at this class can be found here:
https://github.com/jdeolive/geoserver/blob/wfs2/wfs/src/main/java/org/geoserver/wfs/RequestObjectHandler.java
And if you look at say one of the operation classes, like GetFeature, it now
has an additional constructor to take an instance of the request object
handler.

...

https://github.com/jdeolive/geoserver/blob/wfs2/wfs/src/main/java/org/geoserver/wfs/GetFeature.java
Thoughts and feedback or an alterative approach are all welcome. Having to
access all request object properties through the handler is somewhat
tedious... but seemed like a better approach then trying to duplicate or
refactor the operation classes.

The approach obviously works. One thing that makes me hesitant about
it is that the you get an indirection,
a proxy, right in your face, instead of being able to say "ah, this is
my request" you explicitly have to program
with a model saying "here is my request I can't use directly and here
is the tool I use to get anything out of it".

An alternative approach could be to use converters: the parser
generates whatever request object based
on the version, and there is a Converter that turns it into the target
request object that we want to use.
The could would then just program against it knowing nothing about the
original request object.

What could this target request object be? Well.. I guess it depends.
It might be the WFS 2.0 one if it's rich enough that it covers the
same functionality and semantics
as WFS 1.1 and WFS 1.0 (just gives you more, unlike the WCS case where
things are downright different).
Or it might be our own little internal object model that we can evolve
over time, just like we don't have a
EMF thing for filter, styles and feature: if the next spec has more or
demands for something different
we just evolve the internal object model and adapt the converters.

I guess the converter job could be done mostly by reflection is the
properties we are going to convert
are mostly same named, with little manual additions for whatever
cannot be figured out automatically.

Cheers
Andrea

--
-------------------------------------------------------
Ing. Andrea Aime
GeoSolutions S.A.S.
Tech lead

Via Poggio alle Viti 1187
55054 Massarosa (LU)
Italy

phone: +39 0584 962313
fax: +39 0584 962313

http://www.geo-solutions.it
http://geo-solutions.blogspot.com/
http://www.youtube.com/user/GeoSolutionsIT
http://www.linkedin.com/in/andreaaime
http://twitter.com/geowolf

-------------------------------------------------------

On Wed, May 4, 2011 at 3:48 AM, Andrea Aime <andrea.aime@anonymised.com> wrote:

On Tue, May 3, 2011 at 7:24 PM, Justin Deoliveira <jdeolive@anonymised.com> wrote:

My first cut at this class can be found here:
https://github.com/jdeolive/geoserver/blob/wfs2/wfs/src/main/java/org/geoserver/wfs/RequestObjectHandler.java
And if you look at say one of the operation classes, like GetFeature, it now
has an additional constructor to take an instance of the request object
handler.

https://github.com/jdeolive/geoserver/blob/wfs2/wfs/src/main/java/org/geoserver/wfs/GetFeature.java
Thoughts and feedback or an alterative approach are all welcome. Having to
access all request object properties through the handler is somewhat
tedious… but seemed like a better approach then trying to duplicate or
refactor the operation classes.

The approach obviously works. One thing that makes me hesitant about
it is that the you get an indirection,
a proxy, right in your face, instead of being able to say “ah, this is
my request” you explicitly have to program
with a model saying “here is my request I can’t use directly and here
is the tool I use to get anything out of it”.

Agreed, the level of indirection is obviously not convenient to program against.

An alternative approach could be to use converters: the parser
generates whatever request object based
on the version, and there is a Converter that turns it into the target
request object that we want to use.
The could would then just program against it knowing nothing about the
original request object.

What could this target request object be? Well… I guess it depends.
It might be the WFS 2.0 one if it’s rich enough that it covers the
same functionality and semantics
as WFS 1.1 and WFS 1.0 (just gives you more, unlike the WCS case where
things are downright different).
Or it might be our own little internal object model that we can evolve
over time, just like we don’t have a
EMF thing for filter, styles and feature: if the next spec has more or
demands for something different
we just evolve the internal object model and adapt the converters.

Well this is essentially the approach we took for wfs 1.0 → 1.1 and used wfs 1.1 as the core model and the wfs 1.0 parsers essentially converted to it. And indeed I looked at this for wfs 2.0 but after analyzing the object models and schemas I just found that the two were too different. Especially with regard to how they changed all the query stuff… moving it into the fes schema, making it abstract and then extending it from wfs.

One potentially downside to this approach is say we do decide to rewrite all the operations against the wfs 2.0 model. And then we move to 2.1 and it adds stuff. We need to update the entire wfs subsystem again. So a level of indirection isolates us. Which is the same as if we came up with our own internal object model and stuck with that and evolved it over time. But that would sort of defeat the emf parsing chain that we use. Currently because the target is an emf model we actually have to do very little parsing work since the parser can usually figure out how to parse from the emf model metadata. If we move to an internal model we would basically be spending all the time writing converters to that model… i fear that would be on the same level of work as just writing a full parser that parses directly to it.

Anyways, I will investigate a converter approach and see how it measures up against the approach I am currently taking.

I guess the converter job could be done mostly by reflection is the
properties we are going to convert
are mostly same named, with little manual additions for whatever
cannot be figured out automatically.

Cheers
Andrea

Ing. Andrea Aime
GeoSolutions S.A.S.
Tech lead

Via Poggio alle Viti 1187
55054 Massarosa (LU)
Italy

phone: +39 0584 962313
fax: +39 0584 962313

http://www.geo-solutions.it
http://geo-solutions.blogspot.com/
http://www.youtube.com/user/GeoSolutionsIT
http://www.linkedin.com/in/andreaaime
http://twitter.com/geowolf



Justin Deoliveira
OpenGeo - http://opengeo.org
Enterprise support for open source geospatial.

On Wed, May 4, 2011 at 4:19 PM, Justin Deoliveira <jdeolive@anonymised.com> wrote:

Anyways, I will investigate a converter approach and see how it measures up
against the approach I am currently taking.

A compromise could be to use the handler, but make that transparent.
Call it "the request", have a converter that basically takes the wfs request
objects and just wraps them in the handler and forget the original
ones ever existed: you end up using only the handler, but without calling
that way, it's just the "wfs request".

Makes sense? The handler is basically already the "internal object model",
how it's implemented inside (dynamic lookup over other objects, copy
fields) is a detail no?

Cheers
Andrea

--
-------------------------------------------------------
Ing. Andrea Aime
GeoSolutions S.A.S.
Tech lead

Via Poggio alle Viti 1187
55054 Massarosa (LU)
Italy

phone: +39 0584 962313
fax: +39 0584 962313

http://www.geo-solutions.it
http://geo-solutions.blogspot.com/
http://www.youtube.com/user/GeoSolutionsIT
http://www.linkedin.com/in/andreaaime
http://twitter.com/geowolf

-------------------------------------------------------

Ah ha. Yeah that makes a lot of sense. And indeed I was going to break out separate “handler” classes for the different types of objects… but that is in itself a request object model :slight_smile: Just because it is dynamic and working against different “internal” model implementations is really just an implementation detail.

Thanks for the great feedback and ideas Andrea!

On Wed, May 4, 2011 at 8:27 AM, Andrea Aime <andrea.aime@anonymised.com…> wrote:

On Wed, May 4, 2011 at 4:19 PM, Justin Deoliveira <jdeolive@anonymised.com> wrote:

Anyways, I will investigate a converter approach and see how it measures up
against the approach I am currently taking.

A compromise could be to use the handler, but make that transparent.
Call it “the request”, have a converter that basically takes the wfs request
objects and just wraps them in the handler and forget the original
ones ever existed: you end up using only the handler, but without calling
that way, it’s just the “wfs request”.

Makes sense? The handler is basically already the “internal object model”,
how it’s implemented inside (dynamic lookup over other objects, copy
fields) is a detail no?

Cheers
Andrea

Ing. Andrea Aime
GeoSolutions S.A.S.
Tech lead

Via Poggio alle Viti 1187
55054 Massarosa (LU)
Italy

phone: +39 0584 962313
fax: +39 0584 962313

http://www.geo-solutions.it
http://geo-solutions.blogspot.com/
http://www.youtube.com/user/GeoSolutionsIT
http://www.linkedin.com/in/andreaaime
http://twitter.com/geowolf



Justin Deoliveira
OpenGeo - http://opengeo.org
Enterprise support for open source geospatial.