nextgis / nextgis.com-webgis

Public issues for online Web GIS service from nextgis.com. Leave your feedback, problems and suggestions here.
http://nextgis.com
0 stars 1 forks source link

Невозможно подключиться к WFS-сервису посредством Geotools/Geoserver #34

Open asavartsov opened 6 years ago

asavartsov commented 6 years ago

При попытке запросить данные слоя, опубликованного как WFS-сервис при помощи Java-API Geotools или при попытке опубликовать слой из WFS-сервиса, подключенного в Geoserver как datasource возникает исключение

org.geotools.data.DataSourceException: No XSDElementDeclaration found for {http://www.opengis.net/wfs}ngw_id_153
    at org.geotools.data.wfs.internal.parsers.EmfAppSchemaParser.parseFeatureType(EmfAppSchemaParser.java:306)
    at org.geotools.data.wfs.internal.parsers.EmfAppSchemaParser.parse(EmfAppSchemaParser.java:217)
    at org.geotools.data.wfs.internal.DescribeFeatureTypeResponse.<init>(DescribeFeatureTypeResponse.java:65)
    at org.geotools.data.wfs.internal.parsers.DescribeFeatureTypeResponseFactory.createResponse(DescribeFeatureTypeResponseFactory.java:62)
    at org.geotools.data.wfs.internal.WFSRequest.createResponse(WFSRequest.java:220)
    at org.geotools.data.wfs.internal.WFSRequest.createResponse(WFSRequest.java:38)
    at org.geotools.data.ows.AbstractOpenWebService.internalIssueRequest(AbstractOpenWebService.java:445)
    at org.geotools.data.wfs.internal.WFSClient.internalIssueRequest(WFSClient.java:298)
    at org.geotools.data.wfs.internal.WFSClient.issueRequest(WFSClient.java:360)
    at org.geotools.data.wfs.WFSDataStore.getRemoteFeatureType(WFSDataStore.java:210)
    at org.geotools.data.wfs.WFSDataStore.getRemoteSimpleFeatureType(WFSDataStore.java:264)
    at org.geotools.data.wfs.WFSFeatureSource.buildFeatureType(WFSFeatureSource.java:348)
    at org.geotools.data.store.ContentFeatureSource.getAbsoluteSchema(ContentFeatureSource.java:356)
    ... 128 more

Код, который используется для доступа к WFS (Geotools 17.2)

String getCapabilities = "http://xxxxxxxxxx.nextgis.com/api/resource/155/wfs?REQUEST=GetCapabilities&version=1.0.0";
Map connectionParameters = new HashMap();
connectionParameters.put("WFSDataStoreFactory:GET_CAPABILITIES_URL", getCapabilities);
connectionParameters.put("WFSDataStoreFactory:TIMEOUT", "30000");
WFSDataStoreFactory dsf = new WFSDataStoreFactory();

WFSDataStore dataStore = dsf.createDataStore(connectionParameters);
String typeName = "ngw_id_153";
SimpleFeatureSource source = dataStore.getFeatureSource(typeName);
SimpleFeatureCollection fc = source.getFeatures();

while(fc.features().hasNext()){
    SimpleFeature sf = fc.features().next();
    System.out.println(sf.toString());
}

Для воспроизведения ошибки в Geoserver достаточно добавить Store типа "Web Feature Server (NG)", указывающее на WFS-сервис NextGIS и попытаться опубликовать слой.

asavartsov commented 6 years ago

Я сравнил, что возвращает Geoserver и NextGIS.

При запросе GetCapabilities Geoserver отдает пространство имен хранилища слоя вида xmlns:Xxxx="xxxх.xx" в корневом теге, где Xxxx - это имя Workspace, а xxxх.xx - это сконфигурированный для это Workspace'а Namespace URI, а затем в теге FeatureType типы также идут с префиксом имени Workspace

<FeatureType>
  <Name>Xxxx:Map_NavigatorTrack</Name>
  <Title>Map_NavigatorTrack</Title>
  <Abstract/>
  <Keywords>features, Map_NavigatorTrack</Keywords>
  <SRS>EPSG:4326</SRS>
  <LatLongBoundingBox minx="32.1880645751953" miny="42.7488021850586" maxx="44.6430282592773" maxy="52.7779388427734"/>
</FeatureType>

Далее во время валидации XSD библиотека Geotools формирует набор сопоставления типов и соответствующих им XSD. Для слоя, опубликованного на Geoserver'е полное имя типа генерируется как {xxxx.xx}Map_NavigatorTrack, (подставляет его Namespace URI). В кэше XSD имеется запись, соответствующая такому полному имени, так как метод DescribeFeatureType возвращает такой же xmlns, targetNamespace и пр. соответствующие Namespace URI рабочего пространства со слоем (насколько я все это понял).

NextGIS на запрос GetCapabilities отдает

<WFS_Capabilities xmlns="http://www.opengis.net/wfs" xmlns:ogc="http://www.opengis.net/ogc" version="1.0.0">

и FeatureType без префикса

<FeatureType>
  <Name>ngw_id_153</Name>
  <Title>field_all</Title>
  <Abstract/>
  <SRS>EPSG:3857</SRS>
  <Operations>
    <Insert/>
    <Update/>
    <Delete/>
  </Operations>
  <bbox maxx="0" maxy="0" minx="0" miny="0"/>
</FeatureType>

Таким образом, ищется XSD для типа {http://www.opengis.net/wfs}ngw_id_153 - берется namespace по умолчанию, но в кэше XSD лежит тип "{http://featureserver.org/fs}ngw_id_153" image

потому что метод DescribeFeatureType возвращает http://featureserver.org/fs как неймспейс для типа слоя

<schema xmlns:fs="http://featureserver.org/fs" xmlns="http://www.w3.org/2001/XMLSchema" xmlns:gml="http://www.opengis.net/gml" targetNamespace="http://featureserver.org/fs" elementFormDefault="qualified" attributeFormDefault="unqualified" version="0.1">
    <import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/2.0.0/feature.xsd" />
    <element name="ngw_id_153" substitutionGroup="gml:_Feature" type="fs:ngw_id_153_Type" />
    <complexType name="ngw_id_153_Type">

Geotools не может найти XSD для типа и возвращает ошибку.

asavartsov commented 6 years ago

Если подменить в ответе на запрос DescribeFeatureType http://featureserver.org/fs на http://www.opengis.net/wfs, то ошибка пропадает (правда, появляется другая, так как такая же подмена требуется и для метода GetFeature, но там я уже не проверял, так как в чем причина вроде понятно).

drnextgis commented 6 years ago

Спасибо за фидбек, сейчас буду разбираться.