Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

viewparams missing for getFeatureInfo WMS request #1404

Open
emoen opened this issue Nov 4, 2014 · 19 comments
Open

viewparams missing for getFeatureInfo WMS request #1404

emoen opened this issue Nov 4, 2014 · 19 comments

Comments

@bartvde
Copy link
Member

bartvde commented Nov 4, 2014

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

emoen referenced this issue in emoen/openlayers Nov 4, 2014
Add viewparams to list of params when building url for getFeatureInfo.
This enables requesting getFeatureInfo for WMS layers that are from the database - defined as sql-view layers in geoserver.
@emoen
Copy link
Contributor Author

emoen commented Nov 4, 2014

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.

@bartvde
Copy link
Member

bartvde commented Nov 4, 2014

unfortunately there are servers out there that break with extra params that they don't know of

@emoen
Copy link
Contributor Author

emoen commented Nov 4, 2014

but is it still not the user/programmers responsibility to format urls that will be parsed by the servers?

@emoen
Copy link
Contributor Author

emoen commented Nov 5, 2014

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?

emoen referenced this issue in Norwegian-marine-datacentre/arctic-roos Nov 5, 2014
…fo.layerParams to have it included in getFeatureInfo reqeusts

See openlayers ticket: openlayers/openlayers#1404
@chris58
Copy link

chris58 commented Mar 2, 2015

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

@emoen
Copy link
Contributor Author

emoen commented Mar 3, 2015

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.

@chris58
Copy link

chris58 commented Mar 4, 2015

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

@bartvde
Copy link
Member

bartvde commented Mar 4, 2015

you will need to make use of vendorParams on OpenLayers.Control.WMSGetFeatureInfo

@chris58
Copy link

chris58 commented Mar 4, 2015

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?

@emoen
Copy link
Contributor Author

emoen commented Mar 6, 2015

How does the code for configuring the layer look like?

@bartvde
Copy link
Member

bartvde commented Mar 6, 2015

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?

@chris58
Copy link

chris58 commented Mar 6, 2015

@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.

@chris58
Copy link

chris58 commented Mar 9, 2015

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

@emoen
Copy link
Contributor Author

emoen commented Mar 11, 2015

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.

@chris58
Copy link

chris58 commented Mar 11, 2015

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 [notifications@github.com]
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.

@emoen
Copy link
Contributor Author

emoen commented Mar 11, 2015

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 ...

@chris58
Copy link

chris58 commented Mar 16, 2015

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

@emoen
Copy link
Contributor Author

emoen commented Mar 24, 2015

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants