I am developing an web application, where the user is able to view and update some feature attribute of a WFS layer. My problem: the edited data is not saved at all.
Here's the situation:
- GeoServer v2.5
- PostGIS / PostgreSQL database v9.1
- pgAdmin III v1.18.1
- Firefox 31.0 with FireBug extension
The web application uses OpenLayers (v2.13.1) to display OpenStreetMap (OSM) data. A WFS layer is added to the OSM base layer:
fwSaveStrategy = new OpenLayers.Strategy.Save();
fwSaveStrategy.events.register("success", '', showSuccessMsg);
fwSaveStrategy.events.register("failure", '', showFailureMsg);
var layerFootway = new OpenLayers.Layer.Vector("WFS OSM Footway", {
strategies: [new OpenLayers.Strategy.BBOX(), fwSaveStrategy],
protocol: new OpenLayers.Protocol.WFS({
version: '1.1.0',
url: 'http://<the-server-address>/wfs',
featureType: 'view_footway',
srsName: 'EPSG:3857'
}),
extractAttributes: true,
visibility: true,
styleMap: new OpenLayers.StyleMap({
"default": new OpenLayers.Style(OpenLayers.Util.applyDefaults({
fillColor: "#ff00ff",
fillOpacity: 0.5,
strokeColor: "#ff00ff",
strokeOpacity: 0.75,
strokeWidth: 25
}, OpenLayers.Feature.Vector.style["default"])),
"select": new OpenLayers.Style(OpenLayers.Util.applyDefaults({
fillColor: "#00ffff",
fillOpacity: 0.75,
strokeColor: "#00ffff",
strokeOpacity: 0.75,
strokeWidth: 25
}, OpenLayers.Feature.Vector.style["select"]))
})
});
This layer is a specific view in PostgreSQL: the view combines footways/pedestrian sidewalk vector data from OSM with own data of footway attributes (for example surface, type, inclination etc.). Both data sets are joined via the unique OSM ID that is assigned to every object (street, way etc) inside OSM.
For interaction purposes, a user can click/touch on a footway and gets confronted with a popup stating some feature attributes and way attributes. First, the code to achieve this:
var selectControlTouch = new OpenLayers.Control.SelectFeature(layerFootway, {
hover: false,
autoActivate: true,
onSelect: function(feature) {addPopup(feature);},
onUnselect: function(feature) {saveAttributes(feature); deletePopup(feature);}
});
So, by click/touch on a footway, a popup is initiated and displayed on the screen (see picture below). There the user is able to alter a value of the footway attributes (just a few numbers right now to get it working). If the user clicks elsewhere on the map, the changed attribute value will (hopefully) be saved and the popup will be closed.
To be able to store data to the view, I added specific rules to it in PostgreSQL:
The save function of my application looks like this:
function saveAttributes(feature) {
feature.state = OpenLayers.State.INSERT;
feature.attributes.wn_test = document.getElementById('iWn_test').value;
fwSaveStrategy.save(feature);}
So far, so good. Just a roundup:
- I've created a view in PostgreSQL.
- This view is published via GeoServer.
- In OpenLayers it is initiated as a WFS layer and displays correctly inside my browsers.
- If the user clicks on a footway, a popup comes up with some informations about that way.
- Inside the popup lies an
<input>
field. Goal: write that (edited) data back to the database. - Once the user clicks elsewhere on the map, the data from the
<input>
field would be saved and the popup closes.
BUT:
- If I call
fwSaveStrategy.save(feature);
, the transfer seems to execute correctly, but no data will be transfered though giving me an alert message "Everything went fine". - If I call
fwSaveStrategy.save([feature]);
, the response from the server is:view_footway is read-only
.
From my web search, the last message seems common among WFS-T users. So I clicked through several pages, tutorials and message boards (including this one) to find a solution. It seemed, that I needed a Primary Key Metadata table to get updatable views. So I added one with the name gt_pk_metadata_table
to my database:
Then I referenced that table in my GeoServer data store (under "Primary key metadata table") and saved. Unfortunately, that procedure has not solved my problems, it's gotten worse. Before, I could ask for the osm_id
via feature.attributes.osm_id
as this field belongs to the view. Now, with the metadata table, the result for requesting the osm_id
is undefined
. Therefore, the saving function won't execute correctly:
<ows:Exception exceptionCode=InvalidParameterValue>
<ows:ExceptionText>Error performing insert: Source was null in trying to create a reprojected feature collection!</ows:ExceptionText>
Does anyone has any idea, how to solve this and get the application to save the attributes edited via popup? I am dealing with this issue for 3 days now and am more and more willing to write a .php file with an SQL script instead of using WFS-T.
UPDATE 26.08.2014
Just played around a little bit without complicated views and specific rules, but all comes down to one error message:
- created a new table containing OSM data (copied several columns from existing table into new one via
SELECT INTO
) - added a primary key column to that table to get unique ids because osm_id is not unique (via
ALTER TABLE
andSERIAL
) - checked GRANTS in pgAdmin and set
public
and the owner to ALL - tested UPDATE/SELECT in pgAdmin on that new table
- published the table as new layer in GeoServer
- added the new layer in OpenLayers
- all data shows up fine
But as soon as the fwSaveStrategy.save()
function is called, the XML output reads
<ows:Exception exceptionCode="InvalidParameterValue">
<ows:ExceptionText>Update error: Invalid output dimension (must be 2 or 3)</ows:ExceptionText>
I've searched the web for it but found nothing useful. Any ideas?
UPDATE 27.08.2014
Here's the WFS exception:
<ows:ExceptionReport xmlns:ows="http://www.opengis.net/ows"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="1.0.0" xsi:schemaLocation="http://www.opengis.net/ows http://<serveraddress>/geoserver/schemas/ows/1.0.0/owsExceptionReport.xsd">
<ows:Exception exceptionCode="InvalidParameterValue">
<ows:ExceptionText>Update error: Invalid output dimension (must be 2 or 3)</ows:ExceptionText>
</ows:Exception>
</ows:ExceptionReport>
Best Answer
I know this is kind of an OLD thread, but I have looked for two days for an answer to this same error message about output dimensions needing to be 2 or 3. I think i have found a solution that could be useful to your problem as well as mine, so I'm going to share it. It worked for me.
My issue, specifically, was when I converted a bunch of KML's from Google Earth to Shapefiles, and then loaded those shapefiles into my PostGIS db. The PostGIS tables would load in QGIS fine, but would not display when published to Geoserver. The error message (from the WMS) was essentially:
Rendering process failed java.io.IOExceptionOutput dimension must be 2 or 3
So! Here's what I've discovered:
Looking in PostGIS geometry_columns, the tables that would not display had a coord_dimension column value of 4 (which is higher than 2 or 3). It seems that Geoserver does not render 4D features. QGIS does. This was why I was having difficulty finding the problem, the tables were OK, per se.
What I wound up doing was re-saving my shapefiles in QGIS, but I chose the geometry types for my shapefiles (points, lines, and polygons) following the document: http://www.gdal.org/drv_shapefile.html
which basically offers the following information:
SHPT=type: Override the type of shapefile created. Can be one of NULL for a simple .dbf file with no .shp file, POINT, ARC, POLYGON or MULTIPOINT for 2D; POINTZ, ARCZ, POLYGONZ or MULTIPOINTZ for 3D; POINTM, ARCM, POLYGONM or MULTIPOINTM for measured geometries; and POINTZM, ARCZM, POLYGONZM or MULTIPOINTZM for 3D measured geometries. The measure support was added in GDAL 2.1. MULTIPATCH files are not supported.
So, avoiding saving the file as any format that included the M dimension, I was able to bypass the problem of "dimensions must be 2 or 3".
i.e. In QGIS, save your layer as a Shapefile and include
SHPT=POLYGON
in the Layer section of the Custom Options when saving.Hope that helps.