[Geoserver-users] v2.0RC1 app-schema extension: requires gml:id when schema optional?

I'm using the app-schema extension with v2.0 RC1. I followed the tutorial page at <http://docs.geoserver.org/trunk/en/user/tutorials/app-schema/app-schema-tutorial.html&gt; and got that working fine. Now I'm trying to do a mapping from my own database table to the GeoSciML GeologicUnit feature.

A mapping like the below:

-----

<FeatureTypeMapping>
  <sourceDataStore>datastore</sourceDataStore>
  <sourceType>UK_625K_BEDROCK_GEOL_UNIT</sourceType>
  <targetElement>gsml:GeologicUnit</targetElement>
  <attributeMappings>
    <AttributeMapping>
      <targetAttribute>gsml:GeologicUnit</targetAttribute>
      <idExpression>
        <OCQL>getID()</OCQL>
      </idExpression>
    </AttributeMapping>
    <AttributeMapping>
      <targetAttribute>gml:description</targetAttribute>
      <sourceExpression>
        <OCQL>LEX_D</OCQL>
      </sourceExpression>
    </AttributeMapping>
    <AttributeMapping>
      <targetAttribute>gml:name[1]</targetAttribute>
      <sourceExpression>
        <OCQL>NAME_URN</OCQL>
      </sourceExpression>
      <ClientProperty>
        <name>codeSpace</name>
        <value>'http://www.cgi-iugs.org/uri’</value>
      </ClientProperty>
    </AttributeMapping>
    <AttributeMapping>
      <targetAttribute>gsml:preferredAge/gsml:GeologicEvent/gsml:eventAge</targetAttribute>
      <targetAttributeNode>gsml:CGI_TermValuePropertyType</targetAttributeNode>
    </AttributeMapping>
    <AttributeMapping>
    <targetAttribute>gsml:preferredAge/gsml:GeologicEvent/gsml:eventAge/gsml:CGI_TermValue/gsml:value</targetAttribute>
      <sourceExpression>
        <OCQL>ICS_URN</OCQL>
      </sourceExpression>
      <ClientProperty>
        <name>codeSpace</name>
        <value>'http://www.cgi-iugs.org/uri’</value>
      </ClientProperty>
    </AttributeMapping>
  </attributeMappings>
</FeatureTypeMapping>

-----

give the error below in geoserver.log:

-----

2009-09-08 14:33:00,853 WARN [org.geotools.xml] - org.geotools.data.complex.MappingFeatureCollection@...2638... (org.geotools.data.complex.MappingFeatureCollection) is not of type [Lorg.opengis.feature.simple.SimpleFeature;
2009-09-08 14:33:01,040 ERROR [org.geoserver.ows] -
java.lang.NullPointerException: urn:cgi:xmlns:CGI:GeoSciML:2.0:GeologicEventType is identified, null id not accepted
  at org.geotools.feature.type.Types.validate(Types.java:116)
  at org.geotools.feature.type.Types.validate(Types.java:78)
  at org.geotools.feature.AttributeImpl.<init>(AttributeImpl.java:50)
  at org.geotools.feature.ComplexAttributeImpl.<init>(ComplexAttributeImpl.java:35)
  at org.geotools.feature.FeatureImpl.<init>(FeatureImpl.java:64)
  at org.geotools.feature.AppSchemaFeatureFactoryImpl.createFeature(AppSchemaFeatureFactoryImpl.java:112)
  at org.geotools.feature.AttributeBuilder.create(AttributeBuilder.java:552)
  at org.geotools.feature.AttributeBuilder.add(AttributeBuilder.java:472)
  at org.geotools.data.complex.filter.XPath.setValue(XPath.java:691)
  at org.geotools.data.complex.filter.XPath.set(XPath.java:622)
  at org.geotools.data.complex.MappingFeatureIterator.setAttributeValue(MappingFeatureIterator.java:371)
  at org.geotools.data.complex.MappingFeatureIterator.computeNext(MappingFeatureIterator.java:555)
  at org.geotools.data.complex.MappingFeatureIterator.next(MappingFeatureIterator.java:453)
  at org.geotools.data.complex.MappingFeatureIterator.next(MappingFeatureIterator.java:82)
  at org.geotools.xml.Encoder.encode(Encoder.java:665)
  at org.geotools.xml.Encoder.encode(Encoder.java:557)
  at org.geoserver.wfs.xml.GML3OutputFormat.write(GML3OutputFormat.java:170)
  at org.geoserver.wfs.WFSGetFeatureOutputFormat.write(WFSGetFeatureOutputFormat.java:137)
  at org.geoserver.ows.Dispatcher.response(Dispatcher.java:703)
  at org.geoserver.ows.Dispatcher.handleRequestInternal(Dispatcher.java:216)
  at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:153)
  at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)
  at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:875)
  at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:809)
  at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:571)
  at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:501)
  at javax.servlet.http.HttpServlet.service(HttpServlet.java:690)
  at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:269)
  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
  at org.vfny.geoserver.filters.SetCharacterEncodingFilter.doFilter(SetCharacterEncodingFilter.java:108)
  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
  at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:265)
  at org.acegisecurity.intercept.web.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:107)
  at org.acegisecurity.intercept.web.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:72)
  at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
  at org.acegisecurity.ui.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:124)
  at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
  at org.acegisecurity.providers.anonymous.AnonymousProcessingFilter.doFilter(AnonymousProcessingFilter.java:125)
  at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
  at org.acegisecurity.ui.basicauth.BasicProcessingFilter.doFilter(BasicProcessingFilter.java:174)
  at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
  at org.acegisecurity.context.HttpSessionContextIntegrationFilter.doFilter(HttpSessionContextIntegrationFilter.java:249)
  at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
  at org.acegisecurity.util.FilterChainProxy.doFilter(FilterChainProxy.java:149)
  at org.acegisecurity.util.FilterToBeanProxy.doFilter(FilterToBeanProxy.java:98)
  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
  at org.geoserver.filters.LoggingFilter.doFilter(LoggingFilter.java:73)
  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
  at org.geoserver.filters.ReverseProxyFilter.doFilter(ReverseProxyFilter.java:183)
  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
  at org.geoserver.filters.GZIPFilter.doFilter(GZIPFilter.java:41)
  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
  at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
  at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:174)
  at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
  at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:117)
  at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:108)
  at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:174)
  at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:874)
  at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:665)
  at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:528)
  at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:81)
  at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:689)
  at java.lang.Thread.run(Unknown Source)

-----

I can fix this by adding the id mapping below:

-----

<AttributeMapping>
  <targetAttribute>gsml:preferredAge/gsml:GeologicEvent</targetAttribute>
  <idExpression><OCQL>strConcat('pa.ge.', getId())</OCQL></idExpression>
</AttributeMapping>

-----

but I'm not sure why I seem to have to define an idExpression on gsml:GeologicEvent when gml:id is an optional attribute in the GeoSciML schema (http://www.geosciml.org/geosciml/2.0/xsd/geosciml.xsd) and I am not configuring gsml:GeologicEvent to be returned as an independent feature by the WFS. Is GeoServer requiring a gml:id even when optional in the Schema or have I misunderstood the configuration?

Marcus Sen

--
This message (and any attachments) is for the recipient only. NERC
is subject to the Freedom of Information Act 2000 and the contents
of this email and any reply you make may be disclosed by NERC unless
it is exempt from release under the Act. Any material supplied to
NERC may be stored in an electronic records management system.

Sen, Marcus A wrote:

java.lang.NullPointerException: urn:cgi:xmlns:CGI:GeoSciML:2.0:GeologicEventType is identified, null id not accepted

[...]

I can fix this by adding the id mapping below:
<AttributeMapping>
        <targetAttribute>gsml:preferredAge/gsml:GeologicEvent</targetAttribute>
        <idExpression><OCQL>strConcat('pa.ge.', getId())</OCQL></idExpression>
</AttributeMapping>
but I'm not sure why I seem to have to define an idExpression on gsml:GeologicEvent
when gml:id is an optional attribute in the GeoSciML schema
(http://www.geosciml.org/geosciml/2.0/xsd/geosciml.xsd) and I am not configuring
gsml:GeologicEvent to be returned as an independent feature by the WFS.
Is GeoServer requiring a gml:id even when optional in the Schema

Yes. It looks like it requires all features to be identified.

or have I misunderstood the configuration?

No your understanding and solution are correct.

The implementation handles all Features consistently. It was written for simple features, before the possibility of unidentified features nested in complex features was apparent. Their behaviour is inherited from the behaviour of top-level (independent) features.

Identification does have advantages, because any GeologicEvent inlined at one point in the document will be encoded by reference if the same instance is a property of a later feature in the same response.

Does identifying your inner features cause any problems?

Kind regards,

--
Ben Caradoc-Davies <Ben.Caradoc-Davies@anonymised.com>
Software Engineer, CSIRO Exploration and Mining
Australian Resources Research Centre
26 Dick Perry Ave, Kensington WA 6151, Australia

-----Original Message-----
From: Ben Caradoc-Davies [mailto:Ben.Caradoc-Davies@…367…]
Sent: 09 September 2009 09:49

Does identifying your inner features cause any problems?

Our underlying database does not identify the GeologicEvent independently from the parent GeologicUnit but I guess the general solution of appending or prefixing the id of the parent identified feature with some string should always work so probably this isn't a real problem. Others may come across the same error, however, so could the app-schema documentation be updated to include the following points:
- Every feature to be output, even if only appearing nested in container features, must have an idExpression mapping
- Suggested hint for generating id's from containing feature id if no obvious id fields for the contained feature.

(Should documentation change requests be added to the issue tracker? I'm not familiar with the system.)

Marcus Sen

--
This message (and any attachments) is for the recipient only. NERC
is subject to the Freedom of Information Act 2000 and the contents
of this email and any reply you make may be disclosed by NERC unless
it is exempt from release under the Act. Any material supplied to
NERC may be stored in an electronic records management system.

Sen, Marcus A wrote:

Our underlying database does not identify the GeologicEvent independently from the parent GeologicUnit but I guess the general solution of appending or prefixing the id of the parent identified feature with some string should always work so probably this isn't a real problem. Others may come across the same error, however, so could the app-schema documentation be updated to include the following points:
- Every feature to be output, even if only appearing nested in container features, must have an idExpression mapping
- Suggested hint for generating id's from containing feature id if no obvious id fields for the contained feature.

Or we could just fix the behaviour.

(Should documentation change requests be added to the issue tracker? I'm not familiar with the system.)

All bug reports and improvement requests gratefully accepted.

--
Ben Caradoc-Davies <Ben.Caradoc-Davies@anonymised.com>
Software Engineer, CSIRO Exploration and Mining
Australian Resources Research Centre
26 Dick Perry Ave, Kensington WA 6151, Australia