1

I am new to Oracle / GeoServer / WFS-T / Openlayers and I am creating a table that will hold geometry features a user creates/updates.

I would like to have just one record in the table per customer (customerId).

Can I create many polygons/points/lines as one feature in OpenLayers and have that go to GeoServer/WFS-T as one feature that then gets written all in one record in the Oracle Table?

Currently I have it all running but it is creating one record for each feature.

One more thing to note, Oracle does allow this by setting the SDO_GTYPE (geometry type) as a MULTIPOLYGON (2007). I am trying to create multiple features as one record in OpenLayers/ WFS-T / GeoServer.

Is there a setting in the Editable Layer I am missing?

Here is my editable layer:

var saveStrategy = new OpenLayers.Strategy.Save();

        customers = new OpenLayers.Layer.Vector("Customers", {
            strategies: [new OpenLayers.Strategy.BBOX(), saveStrategy],
            projection: new OpenLayers.Projection("EPSG:2236"),
            protocol: new OpenLayers.Protocol.WFS({
                version: "1.1.0",
                srsName: "EPSG:2236",
                url: "http://server01:8085/geoserver/sf/wfs",
                featurePrefix: "sf",
                featureType: "customers",
                featureNS: "http://a.org/layers01",
                geometryName: "GEOMETRY"
            })
        });

This is the feature added method:

function FeatureAdded(object)
        {

            var added_feature = object.feature;
            added_feature.state = OpenLayers.State.INSERT;

            // Setup Customer Id for inserting to one record
            // NOTE: This is not working, it just creates multiple records
            //       with the next id number (seed)
            added_feature.attributes.customerId = 123456;

            saveStrategy.save();

        }

When I set the strategy to OpenLayers.Strategy.BBOX(), I get multiple records created in the table. (I am looking to create just one MultiPolygon record in the table.) When I set the strategy to OpenLayers.Strategy.Fixed(), I get no client error (fail method for the strategy does not fire), no GeoServer log error and no records written to the table.

Update # 1

As requested, here is a sample post request. In this case I created two polygons which I only wanted to be one record, but it created two records in the table:

<wfs:Transaction xmlns:wfs="http://www.opengis.net/wfs" service="WFS" version="1.1.0"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs
 http://schemas.opengis.net/wfs/1.1.0/wfs.xsd">
<wfs:Insert>
  <feature:CUSTOMERS xmlns:feature="http://a.org/layers01">
    <feature:GEOMETRY>
      <gml:MultiSurface xmlns:gml="http://www.opengis.net/gml" srsName="EPSG:2236">
        <gml:surfaceMember>
          <gml:Polygon>
            <gml:exterior>
              <gml:LinearRing>
                <gml:posList>701479.552253 437319.29214775 799997.3100655 437319.29214775 799997.3100655
                             436384.8351165 701092.880378 436223.72183525 700899.5444405 436771.5069915
                             701479.552253 437319.29214775
                </gml:posList>
              </gml:LinearRing>
            </gml:exterior>
          </gml:Polygon>
        </gml:surfaceMember>
      </gml:MultiSurface>
    </feature:GEOMETRY>
    <feature:CUSTOMERID>123456</feature:CUSTOMERID>
  </feature:CUSTOMERS>
</wfs:Insert>
<wfs:Insert>
  <feature:CUSTOMERS xmlns:feature="http://a.org/layers01">
    <feature:GEOMETRY>
      <gml:MultiSurface xmlns:gml="http://www.opengis.net/gml" srsName="EPSG:2236">
        <gml:surfaceMember>
          <gml:Polygon>
            <gml:exterior>
              <gml:LinearRing>
                <gml:posList>701608.442878 435611.4913665 700738.43115925 434805.92496025 701253.99365925
                             433968.13589775 702059.5600655 434258.139804 701608.442878 435611.4913665
                </gml:posList>
              </gml:LinearRing>
            </gml:exterior>
          </gml:Polygon>
        </gml:surfaceMember>
      </gml:MultiSurface>
    </feature:GEOMETRY>
    <feature:CUSTOMERID>123456</feature:CUSTOMERID>
  </feature:CUSTOMERS>
</wfs:Insert>
</wfs:Transaction>

Update # 2

I tried removing all features and replacing them as one mpolygon:

// Add Polygons to a MultiPolygon 
            function cmd_Poly_add()
            {

                var features = customers.features;

                var polygons = [];
                var f = null;

                for (f in features)
                {
                    polygons.push(features[f].geometry);
                }

                var myCombinedFeature = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.MultiPolygon(polygons));
                myCombinedFeature.state = OpenLayers.State.INSERT;
                customers.removeFeatures(features);
                customers.addFeatures([myCombinedFeature]);
                customers.redraw();

            }



function FeatureAdded(object)
{

cmd_Poly_add()

}

I then checked the wfs transaction being sent but when I perform the above, the data is getting removed from the body of the wfs:insert.

The original node goes to this level:

 <wfs:Insert>
  <feature:CUSTOMERS xmlns:feature="http://a.org/layers01">
    <feature:GEOMETRY>
      <gml:MultiSurface xmlns:gml="http://www.opengis.net/gml" srsName="EPSG:2236">
        <gml:surfaceMember>
          <gml:Polygon>
            <gml:exterior>
              <gml:LinearRing>
                <gml:posList>

Once I create the new polygon with the line:

customers.addFeatures([myCombinedFeature]);

Everything is gone and only creates a transaction to this level:

<wfs:Insert>
  <feature:CUSTOMERS xmlns:feature="http://a.org/layers01">
    <feature:GEOMETRY>
      <gml:MultiSurface xmlns:gml="http://www.opengis.net/gml" srsName="EPSG:2236">

And I can see it going into the loop and adding the features:

... for (f in features) { polygons.push(features[f].geometry); } ...

To the multipolygon but the transaction is empty as shown above.

Update #3

Update #3 Contains the changes suggested by ahocevar below to move the call to cmd_Poly_add to the save method. This is the error coming back from GeoServer now:

Error performing insert: null

The above error actually makes sense. Since the mpolygon is not being sent back to GeoServer with spatial data (see # 5 below).

To recap what I am currently trying now, here are the details:

  1. I am only calling cmd_Poly_add (the method to combine the polygons into one mpolygon) one time. As recommend by ahocevar below, the place I am calling cmd_Poly_add now is in the save method which is called only once instead of placing it in the FeatureAdded method which was called every time a new feature is added:

    // Save var save = new OpenLayers.Control.Button({ title: "Save Changes", trigger: function () { if (edit.feature) { edit.selectControl.unselectAll(); }

                    cmd_Poly_add();
    
                    saveStrategy.save();
                },
                displayClass: "olControlSaveFeatures"
            });
    
  2. In the cmd_Poly_add, I am using .features method instead of .selectedFeatures method to make sure all features are selected from the layer. (If I use .selectedFeatures, none of the newly drawn polygons are selected):

var features = customers.features;

  1. Also, the customerId is set only once for the mpolygon. (It is no longer set in the FeatureAdded method for every feature):

myCombinedFeature.attributes.customerId = 123456;

Here is the revised method:

// add Polygons to a MultiPolygon 
            function cmd_Poly_add()
            {

                var features = customers.features;
                //var features = wfs_polygon.selectedFeatures;

                var polygons = [];
                var f = null;

                for (f in features) {
                    polygons.push(features[f].geometry);
                }

                var myCombinedFeature = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.MultiPolygon(polygons));

                myCombinedFeature.state = OpenLayers.State.INSERT;

                myCombinedFeature.attributes.customerId = 123456;

                customers.removeFeatures(features);
                customers.addFeatures([myCombinedFeature]);
                customers.redraw();

            }
  1. As noted above, the FeatureAdded is empty now: (Since we are setting the attributes in the cmd_Poly_add method above only once for the newly created mpolygon:

    function FeatureAdded(object)
    {
    }
    
  2. Here are the results, as you can see (same as explained in Update #2), it does create just one tree now (one mpolygon) But, the interior nodes containing the spatial information are not being created for the mpolygon:

...

<wfs:Insert>
<feature:CUSTOMERS xmlns:feature="http://a.org/layers01">
<feature:GEOMETRY>
<gml:MultiSurface xmlns:gml="http://www.opengis.net/gml" srsName="EPSG:2236"/>
</feature:GEOMETRY>
<feature:CUSTOMERID>123456</feature:CUSTOMERID>
</feature:CUSTOMERS>
</wfs:Insert>

...

Update # 4

I am now trying to focus on understanding why the multipolygon is missing the spatial data. That is the main problem. (See section 5 above from update #3)

Inside the cmd_Poly_add function is where the problem must be. The first step is to get all the features that where drawn:

var features = customers.features;

Then "just" the geometry is pushed to an array:

for (f in features) {
                        polygons.push(features[f].geometry);
                    }

Finally a new feature is created called myCombinedFeature which holds the polygon array:

var myCombinedFeature = new OpenLayers.Feature.Vector(new   
OpenLayers.Geometry.MultiPolygon(polygons));

At that point is where the problem must be. Somehow the spatial data is not going over from the polygons array to the Multipolygon (myCombinedFeature).

One important thing I noticed is the myCombinedFeature object has this property:

myCombinedFeature.geometry.components = []

while the features has the spatial data:

features[0].geometry.components = [[POLYGON((7..

And finally the polygon features are removed and the Multipolygon is added to the layer as one new feature:

customers.removeFeatures(features);
customers.addFeatures([myCombinedFeature]);
customers.redraw();

Once the save button is clicked on and the save is executed:

// Save
                var save = new OpenLayers.Control.Button({
                    title: "Save Changes",
                    trigger: function () {
                        if (edit.feature) {
                            edit.selectControl.unselectAll();
                        }

                        cmd_Poly_add();

                        saveStrategy.save();
                    },
                    displayClass: "olControlSaveFeatures"
                });

The spatial data does not go back to GeoServer and an error is produced. (See section 5 above from update #3)

Update #5

The problem is definitely on how myCombinedFeature is getting built. I did a test line as follows:

Right below this line:

var myCombinedFeature = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.MultiPolygon(polygons));

I added this line to override the objects to hold just one point:

 myCombinedFeature = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(701864.0014, 435534.8233));

And the feature is succesfully updated in the table! So the problem is definitely in the "polygons" object! Somehow the points are not going from the "polygons" object into the "myCombinedFeature" object.

closed as too broad by PolyGeo Dec 6 '18 at 21:14

Please edit the question to limit it to a specific problem with enough detail to identify an adequate answer. Avoid asking multiple distinct questions at once. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

  • Can you show us an example of the post request? It should work if geometry is multipolygon – Ian Turton Feb 26 '15 at 20:02
2

I do this by using MultPolygon, as you've mentioned above.

The trick I've used is that after drawing a polygon (when your FeatureAdded function is called) it should add a polygon to a JavaScript object that mirrors the structure of a MultiPolygon. Here's a quick pointer on doing that type of wrapping/unwrapping:

http://osgeo-org.1560.x6.nabble.com/Multipolygon-to-Polygons-td5003436.html

Then, have your Save Strategy send that MultiPolygon. I actually don't use SaveStrategy, but build the save functions myself...

I don't know of a simple setting that does all this for you.

  • Jay, please see update above. I tried the link you mentioned but all feature data is removed when I combine into one MultiPolygon. – user3657279 Mar 2 '15 at 16:01
  • You are creating a nested multipolygon here. This will not work. I would create the multipolygon right before saving, not earlier. – ahocevar Mar 2 '15 at 20:07
  • ahocevar, thanks for your help. I moved the call to cmd_Poly_add() to the save button right before calling saveStrategy.save() and it does the exact same thing. It does not create the body of the mpolygon as shown above. – user3657279 Mar 2 '15 at 21:29
0

You could try creating a view on top of the source data, and the view could be consumed by GeoServer and displayed. On the way back (transaction), it could be done with Materialized View, see http://docs.oracle.com/cd/B10501_01/server.920/a96567/repmview.htm

I never tried such thing, just an idea, what could work

  • Thanks Jachym, I am very close to getting it to work with above methods using WFS-T. The only problem is I would like to create on multipolygon instead of many polygons. This way I can always maintain a one to one ratio per customerId. Jay has the method in his suggestion but cannot get it to work properly. – user3657279 Mar 2 '15 at 19:42

Not the answer you're looking for? Browse other questions tagged or ask your own question.