viewparams missing for getFeatureInfo WMS request
When querying an sql view WMS layer for getFeatureInfo the viewparams is missing.
An example of this: http://maps.imr.no/geoserver/wms?LAYERS=measurements_last_30_days&QUERY_LAYERS=measurements_last_30_days&STYLES=arcticroos_gtsbathy&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetFeatureInfo&BBOX=-10707220.5,-2714812.5,10707220.5,2714812.5&FEATURE_COUNT=10&HEIGHT=375&WIDTH=1479&FORMAT=image/png&INFO_FORMAT=application/vnd.ogc.gml&SRS=EPSG:3575&X=665&Y=365
which has been generated by OpenLayers.Control.WMSGetFeatureInfo.buildWMSOptions() and the response is:
<wfs:FeatureCollection xmlns="http://www.opengis.net/wfs" xmlns:wfs="http://www.opengis.net/wfs" xmlns:gml="http://www.opengis.net/gml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://maps.imr.no:80/geoserver/schemas/wfs/1.0.0/WFS-basic.xsd"> gml:boundedBy gml:nullunknown/gml:null /gml:boundedBy /wfs:FeatureCollection
adding viewparams:type=BA returns the expected result: http://maps.imr.no/geoserver/wms?LAYERS=measurements_last_30_days&QUERY_LAYERS=measurements_last_30_days&STYLES=arcticroos_gtsbathy&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetFeatureInfo&BBOX=-10707220.5,-2714812.5,10707220.5,2714812.5&FEATURE_COUNT=10&HEIGHT=375&WIDTH=1479&FORMAT=image/png&INFO_FORMAT=application/vnd.ogc.gml&SRS=EPSG:3575&X=665&Y=365&viewparams=type:BA
IMHO this should be up to the application to manage through the use of vendorParams:
https://github.com/openlayers/openlayers/blob/master/lib/OpenLayers/Control/WMSGetFeatureInfo.js#L109:L119
Is there not a better way of adding custom properties?
If vendorParams isnt an obscure and hidden variable enough - you get code like this when creating a WMS layer: https://gist.github.com/emoen/febc90cb67f3b2a0e7bb
Would it not be better to add any parameter to the url - openlayers can provide an error-message based on vendor specific parameters anyway. So then the programmer/user is responsible for adding the correct vendor specific parameters.
unfortunately there are servers out there that break with extra params that they don't know of
but is it still not the user/programmers responsibility to format urls that will be parsed by the servers?
If you define a WMS layer:
var felayer = new OpenLayers.Layer.WMS(
'layer name',
WMS_SERVER_URL,
{
layers: "measurements_last_30_days",
transparent: true,
styles: style,
viewparams : 'type:BA'
},
{
isBaseLayer: false
}
);
Then all the parameters are automagically added to getMap requests (also viewparams), but viewparams is not added to getFeatureInfo requests. This is strange as they are both part of the WMS specification.
You have to add
gxp.plugins.WMSGetFeatureInfo.prototype.layerParams = ["viewparams"];to also have that parameter added to getFeatureInfo requests. Which means defining viewparams twice.
Why cant viewparams be added to getFeatuerInfo in the same way it is added to getMap requests?
Hei everybody!
Just found this thread. :-) I have the same problem. I have several layers which result in SQL queries to geoserver. The only difference is a 'viewparams' parameter. When displaying the layer the viewparams are added, but getFeatureInfo does not add these params, so the features returned are usually too many. Is there any way to tell getFeatureInfo to append the viewparams from the layer definitions? I tried gxp.plugins.WMSGetFeatureInfo.prototype.layerParams = ["viewparams"]; but got the error that gxp is not defined.
Regards Christian
If your not using gxp - and you have added viewparams to your OpenLayers.layer.WMS configuration then you probably need to set vendorParams=viewparams in WMSGetFeatureInfo as Bart mentioned above.
I dont think vendorParams should be in WMSGetFeatureInfo as it should be the user/programmers responsibility to format urls correctly for the given WMS server. If the given WMS server doesnt support viewparams then it makes no sense to query that server for a postgis layer.
Hei and thank you for your reply. When adding viewparams to a WMS layer definition they are added to the query, but when clicking on a feature and then requesting feature info the parameters are not added. In case of GeoServer the default viewparams for that layer are then used, which is not what I want in my case. But how can I add viewparams to specific layers. in WMSGetFeatureInfo? Adapting your example case, I would like features of type:BA and type BB, but not features of type:BC? Not doing anything will return the features of the default type (in case of GeoServer). Will adding type:BA;type:BB return features for layers of both types?
I was thinking of addapting the following code http://lin-ear-th-inking.blogspot.no/2013/06/how-to-get-openlayers-wmsgetfeatureinfo.html to viewParams instead of CQLfilter. Would that be the right direction to go?
Hilsen
Christian
you will need to make use of vendorParams on OpenLayers.Control.WMSGetFeatureInfo
That works well when only having ONE layer and adding some parameters to it. But when you have 2 layers which have different viewparams it doesn't. If you specify vendorparams like {viewparams: 'type:A;type:B'} both viewparams are appended but only the last is recognized by geoserver and then applied to both layers, thus returning the same feature info twice. It doesn't help either to change vendorparams to {viewparams:'type: Ä́', viewparams:'type: B'}. It results in only appending the second viewparam to the url with the same result of returning a feature twice. Maybe it's a geoserver issue?
How does the code for configuring the layer look like?
I see your point @chris58 you would need vendorParams to be a lookup per layer name or something similar
Maybe we should add an extra event here where you could intercept the url and add the params yourself?
@bartvde, that's the problem. ;-) I haven't figured out how to associate one set of viewParams/vendorParms with layer ONE and another set of params with layer TWO where the layers ONE and TWO have the same basic definition, i.e. @emoen the code looks like
var one = new OpenLayers.Layer.WMS(
"Accidents 1: Tank", url,
{
LAYERS: 'marenor:VesselAccident',
transparent: "TRUE",
viewparams: 'fartoeystype:1\%'
},
{
visibility: false,
isBaseLayer: false
}
);
var two = new OpenLayers.Layer.WMS(
"Accidents 2: Bulk/Tank", url,
{
LAYERS: 'marenor:VesselAccident',
transparent: "TRUE",
viewparams: 'fartoeystype:2\%'
},
{
visibility: false,
isBaseLayer: false
}
);
But, maybe it's really a geoserver problem of how to pick up and use the vendorParams in a query. I could add the parameters myself by using beforeGetFeatureInfo() but it's still one call with a list of all layers and all viewParams.
Hi again,
found the solution. Just to round up... ;-)
view parameters (geoserver) have to be separated by commas (,) when applying different parameters to several layers (http://docs.geoserver.org/stable/en/user/data/database/sqlview.html?highlight=viewparams). Number of comma separated viewParams must equal number of queried layers.
layersToBeQueried = [layerA, layerB, layerC];
controls.push(new OpenLayers.Control.WMSGetFeatureInfo({ autoActivate: true, infoFormat: "application/vnd.ogc.gml", maxFeatures: 5, queryVisible: true, eventListeners: { beforegetfeatureinfo: function(event) { var retArray = new Array(); var vParams = new Array(); var layer; for(var i = 0; i < layersToBeQueried.length; i++) { if(layersToBeQueried[i].visibility == true){ layer = layersToBeQueried[i]; // check for eventual viewParams if (layer.params.VIEWPARAMS != null){ vParams.push(layer.params.VIEWPARAMS); } else vParams.push('x:0'); // just to have something. Number of params must equal number of layers retArray.push(layer); } } // put view parameters into a string var viewparams = ''; for (i=vParams.length-1; i>=0; i--){ viewparams += vParams[i]; viewparams += (i>0)? ',' : ''; } // alert(viewparams); // add a buffer of 20 pixels around 'click' pluss the viewParams this.vendorParams = (vParams.length > 0)? {'buffer':20, 'viewParams': viewparams} : {buffer:20}; // set the layers to be queried this.layers = retArray; }, "getfeatureinfo": function(e) { // show the info in a popup... } } }));
Regards Christian
How does the url that is sent to geoserver look like? Do you send viewparams: 'fartoeystype:1, 2'? So it is creating a list? I worked around the problem of sending a list of values for one viewparams to geoserver;e.g. &VIEWPARAMS=periodname:'M200405 M200505', by creating a stored procedure tokenizes the elements and returns a select.
In your case the generated viewparams in the getfeatureinfo URL should look like: &VIEWPARAMS=periodname:M200405,periodname:M200505
In my case the generated query to geoserver looks like this
http://some.host.com/geoserver/marenor/wms?LAYERS=marenor%3AVesselAccident,marenor%3AVesselAccident&QUERY_LAYERS=marenor%3AVesselAccident,marenor%3AVesselAccident&STYLES=,&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetFeatureInfo&BBOX=125573.169586%2C-2128225.949283%2C1227600.259337%2C-1731099.070094&FEATURE_COUNT=5&HEIGHT=360&WIDTH=999&FORMAT=image%2Fpng&INFO_FORMAT=application%2Fvnd.ogc.gml&SRS=EPSG%3A3575&X=442&Y=234&BUFFER=20&VIEWPARAMS=fartoeystype%3A9%25%2Cfartoeystype%3A7%25
or, a bit more readable like this http://some.host.com/geoserver/marenor/wms?LAYERS=marenor:VesselAccident,marenor:VesselAccident&QUERY_LAYERS=marenor:VesselAccident,marenor:VesselAccident&STYLES=,&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetFeatureInfo&BBOX=125573.169586,-2128225.949283,1227600.259337,-1731099.070094&FEATURE_COUNT=5&HEIGHT=360&WIDTH=999&FORMAT=image/png&INFO_FORMAT=application/vnd.ogc.gml&SRS=EPSG:3575&X=442&Y=234&BUFFER=20&VIEWPARAMS=fartoeystype:9%,fartoeystype:7%
The query starts with the two LAYERS which are identical ?LAYERS=marenor:VesselAccident,marenor:VesselAccident
The only difference is the view parameter at the end of the URL &VIEWPARAMS=fartoeystype:9%,fartoeystype:7%
The view parameter sets must be separated by commas and equal the number of layers. If a layer needs more than one view parameter the parameters for that layer must be separated by semi colons. Example: &VIEWPARAMS=fartoeystype:9%;accidenttype:gounding,fartoeystype:7% fartoeystype:9% and accidenttype:grounding are applied to the first layer, fartoeystype,:7% is applied to the second layer.
The percentage symbol is sent directly to the underlying database, it's an SQL wild card character, in this case 9% means look for everything which starts with a 9.
What you have to build up as vendorParams in Control.WMSGetFeatureInfo (for two layers, one view parameter each) looks like this.vendorParams = {buffer:20, viewParams: 'fartoeystype:9%,fartoeystype:7%'}
The buffer is another vendor parameter special to geoserver, in this case defining a 20 pixel buffer around the click position when searching for features.
Regards Christian
From: Endre Moen [[email protected]] Sent: Wednesday, March 11, 2015 9:35 AM To: openlayers/openlayers Cc: Christian Steinebach Subject: Re: [openlayers] viewparams missing for getFeatureInfo WMS request (#1404)
How does the url that is sent to geoserver look like? Do you send viewparams: 'fartoeystype:1, 2'? So it is creating a list? I worked around the problem of sending a list of values for one viewparams to geoserver;e.g. &VIEWPARAMS=periodname:'M200405 M200505', by creating a stored procedure tokenizes the elements and returns a select.
� Reply to this email directly or view it on GitHubhttps://github.com/openlayers/openlayers/issues/1404#issuecomment-78223256.
So does geoserver generates a query where you have SELECT * FROM ... WHERE ... AND fartoeystype=9% AND fartoeystype=7% AND ...?
I needed to generate an SQL that uses OR which is why I did it with a stored procedure: SELECT * FROM ... WHERE ... AND periodname=M200405 OR periodname=M200505 AND ...
Sorry @emoen for late reply. Saw it first now. :-(
Geoserver doesn't generate any AND or OR in an SQL query. It just replaces the text between two percentage signs with the value of the paramter. You could fake it by using a query like
Select ... from ... where periodname='%period_1%' or periodname='%period_2%' or periodname='%period_3%'
Then your viewparams would be called period_1, period_2, period_3. If you set the default parameter values to something which will never exist in the table, e.g. -1, the query will work with one, two or all three period_X mentioned in the query.
If you want to build more complicated selections it could be an idea to use CQL filters instead.
Christian
hi @chris58 , we have probably hijacked this issue...
If your using geoserver-sql-view each key,value pair of VIEWPARAMS is matched to a column in a table or view and geoserver generates an sql like this:https://gist.github.com/emoen/8a6e2c2554ba177a26ae give a request with: VIEWPARAMS=parameter_name:Test_febr2014;grid:NorMar;...
Your right, CQL is the way to do it rather than a stored procedure.