Harvesting CSW (ISO) Geoserver not working with Geonetwork CSW

Harvesting CSW (ISO) Geoserver not working with Geonetwork CSW

I have a problem Harvesting a Geoserver CSW Service from Geonetwork,
so to be sure i started fresh from scratch

Pasted the war a fresh Tomcat 9.0 webapps directory
geoserver-2.26.1-war

Stopped Geoserver from tomcat manager

Added this extensions
geoserver-2.26.1-metadata-plugin
geoserver-2.26.1-csw-plugin
geoserver-2.26.1-csw-iso-plugin

Added all files described in “INSPIRE metadata configuration using metadata and CSW”

Started Geoserver

In the browser i type (server url is not shown):

/geoserver/csw?request=GetRecords
&service=CSW
&version=2.0.2
&resultType=results
&outputFormat=application/xml
&startPosition=1
&maxRecords=20
&elementSetName=summary
&typeNames=gmd:MD_Metadata
&namespace=(can't add due post restrictions; 
&outputSchema=http://www.isotc211.org/2005/gmd

And i get :

<csw:GetRecordsResponse version="2.0.2" xsi:schemaLocation=". . .  omissis . . .">
	<csw:SearchStatus timestamp="2024-11-27T14:16:48.341Z"/>
	<csw:SearchResults numberOfRecordsMatched="0" numberOfRecordsReturned="0" nextRecord="0" recordSchema=". . .  omissis . . ." elementSet="summary"/>
</csw:GetRecordsResponse>

Ok so far.

Then if i add a uuid in the sample “World rectangle” layer.
Then Save.

In i retry the above GetRecords i get :

<ows:ExceptionReport version="1.0.0" xsi:schemaLocation=". . .  omissis . . .">
	<ows:Exception exceptionCode="NoApplicableCode">
		<ows:ExceptionText>
			javax.xml.transform.TransformerException: java.lang.RuntimeException: Can't get the id for a composite featurecollection; you need to identify the consituent collections
			directly. java.lang.RuntimeException: Can't get the id for a composite featurecollection; you need to identify the consituent collections directly. Can't get the id
			for a composite featurecollection; you need to identify the consituent collections directly.
		</ows:ExceptionText>
	</ows:Exception>
</ows:ExceptionReport>

If i instead try with

&elementSetName=full
(instead of &elementSetName=summary)

I get the valid answer.

<csw:GetRecordsResponse version="2.0.2" xsi:schemaLocation=". . .  omissis . . .">
	<csw:SearchStatus timestamp="2024-11-27T14:21:56.896Z"/>
	<csw:SearchResults numberOfRecordsMatched="1" numberOfRecordsReturned="1" nextRecord="0" recordSchema=". . .  omissis . . ." elementSet="full">
		<gmd:MD_Metadata>
			<gmd:fileIdentifier>
				<gco:CharacterString>7169c67d-a2e6-4084-8c76-5ddcbbdca696</gco:CharacterString>
			</gmd:fileIdentifier>
			 . . . and so on . . .

The problems is the Geonetwork 4.4.6 CSW harvesting uses “&elementSetName=summary” and i can’t find a way to work around.

What’s wrong and what can i do about it ?

Thank you, best regards

The missing part is

&namespace=xmlns(csw=http://www.opengis.net/cat/csw/2.0.2),xmlns(gmd=GMD — Resource site for ISO/TC 211 Geographic information/Geomatics)

I am not sure I completely understand, is this a geonetwork problem or a geoserver problem?

Why does geonetwork use elementSetName=summary?

The code for GeoServer CSW is here: [GetRecords[(geoserver/src/extension/csw/core/src/main/java/org/geoserver/csw/GetRecords.java at main · geoserver/geoserver · GitHub). It looks like summary is the default.

Is GeoNetwork expecting more information in the summary than what is provided?

Q: I cannot find the error message about “Can’t get the id for a composite featurecollection” in the codebase for geoserver or geonetwork? Where does it come from …

Hi Jive.
Thanks for your time.

Tecnically i think that is a problem of Geoserver.

If i follow the iso19139 standard i should get a result even in
elementSetName=summary
or
elementSetName=brief

Afterall the difference should be only about the metadata fields that i get back.

The standard defines three levels of informations :

Brief

dc:identifier
dc:title
dc:type
ows:BoundingBox

Summary

dc:format
dc:identifier
dc:relation
dc:subject
dc:title
dc:type
dct:abstract
dct:modified
ows:BoundingBox

Full

csw:AnyText
dc:contributor
dc:coverage
dc:creator
dc:date
dc:description
dc:format
dc:identifier
dc:language
dc:publisher
dc:relation
dc:rights
dc:source
dc:subject
dc:title
dc:type
dct:abstract
dct:modified
dct:spatial
ows:BoundingBox

So summary should be “easier” and light then full

About Geonetwork no idea why it uses SUMMARY, but i don’t think can be changed.

The error message comes from here (the only one i found) :
geoserver-2.26.1\src\main\src\main\java\org\geoserver\feature\CompositeFeatureCollection.java

Rows 66 to 70

@Override
public String getID() {
throw new RuntimeException(
“Can’t get the id for a composite featurecollection; you need to identify the consituent collections directly.”);
}

Full Stack error is :

org.geoserver.platform.ServiceException: javax.xml.transform.TransformerException:
java.lang.RuntimeException: Can’t get the id for a composite featurecollection; you need to identify the consituent collections directly.
at org.geoserver.csw.response.MetaDataResponse.transformResponse(MetaDataResponse.java:37)
at org.geoserver.csw.response.AbstractRecordsResponse.write(AbstractRecordsResponse.java:100)
at org.geoserver.ows.Dispatcher.response(Dispatcher.java:1058)
at org.geoserver.ows.Dispatcher.handleRequestInternal(Dispatcher.java:273)
at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:177)
at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:51)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1072)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:965)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:529)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:623)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:199)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:144)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:168)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:144)
at org.geoserver.filters.ThreadLocalsCleanupFilter.doFilter(ThreadLocalsCleanupFilter.java:28)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:168)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:144)
at org.geoserver.filters.SpringDelegatingFilter$Chain.doFilter(SpringDelegatingFilter.java:73)
at org.geoserver.ows.HTTPHeadersCollector.doFilter(HTTPHeadersCollector.java:48)
at org.geoserver.filters.SpringDelegatingFilter$Chain.doFilter(SpringDelegatingFilter.java:70)
at org.geoserver.filters.HTTPMethodFilter.doFilter(HTTPMethodFilter.java:36)
at org.geoserver.filters.SpringDelegatingFilter$Chain.doFilter(SpringDelegatingFilter.java:70)
at org.geoserver.filters.LoggingFilter.doFilter(LoggingFilter.java:194)
at org.geoserver.filters.SpringDelegatingFilter$Chain.doFilter(SpringDelegatingFilter.java:70)
at org.geoserver.filters.SpringDelegatingFilter.doFilter(SpringDelegatingFilter.java:43)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:168)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:144)
at org.geoserver.platform.AdvancedDispatchFilter.doFilter(AdvancedDispatchFilter.java:39)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:168)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:144)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:352)
at org.geoserver.security.filter.GeoServerCompositeFilter$NestedFilterChain.doFilter(GeoServerCompositeFilter.java:71)
at org.springframework.security.web.access.intercept.AuthorizationFilter.doFilter(AuthorizationFilter.java:100)
at org.geoserver.security.filter.GeoServerCompositeFilter$NestedFilterChain.doFilter(GeoServerCompositeFilter.java:75)
at org.geoserver.security.filter.GeoServerCompositeFilter.doFilter(GeoServerCompositeFilter.java:92)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:361)
at org.geoserver.security.filter.GeoServerCompositeFilter$NestedFilterChain.doFilter(GeoServerCompositeFilter.java:71)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:126)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:120)
at org.geoserver.security.filter.GeoServerCompositeFilter$NestedFilterChain.doFilter(GeoServerCompositeFilter.java:75)
at org.geoserver.security.filter.GeoServerCompositeFilter.doFilter(GeoServerCompositeFilter.java:92)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:361)
at org.geoserver.security.filter.GeoServerAnonymousAuthenticationFilter.doFilter(GeoServerAnonymousAuthenticationFilter.java:53)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:361)
at org.geoserver.security.filter.GeoServerCompositeFilter$NestedFilterChain.doFilter(GeoServerCompositeFilter.java:71)
at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilterInternal(BasicAuthenticationFilter.java:168)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.geoserver.security.filter.GeoServerCompositeFilter$NestedFilterChain.doFilter(GeoServerCompositeFilter.java:75)
at org.geoserver.security.filter.GeoServerCompositeFilter.doFilter(GeoServerCompositeFilter.java:92)
at org.geoserver.security.filter.GeoServerBasicAuthenticationFilter.doFilter(GeoServerBasicAuthenticationFilter.java:81)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:361)
at org.geoserver.security.filter.GeoServerCompositeFilter$NestedFilterChain.doFilter(GeoServerCompositeFilter.java:71)
at org.geoserver.security.filter.GeoServerSecurityContextPersistenceFilter$1.doFilterInternal(GeoServerSecurityContextPersistenceFilter.java:74)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.geoserver.security.filter.GeoServerCompositeFilter$NestedFilterChain.doFilter(GeoServerCompositeFilter.java:75)
at org.geoserver.security.filter.GeoServerCompositeFilter.doFilter(GeoServerCompositeFilter.java:92)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:361)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:225)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:190)
at org.geoserver.security.GeoServerSecurityFilterChainProxy.doFilter(GeoServerSecurityFilterChainProxy.java:141)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:354)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:267)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:168)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:144)
at org.geoserver.filters.XFrameOptionsFilter.doFilter(XFrameOptionsFilter.java:116)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:168)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:144)
at org.geoserver.filters.GZIPFilter.doFilter(GZIPFilter.java:48)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:168)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:144)
at org.geoserver.filters.SessionDebugFilter.doFilter(SessionDebugFilter.java:49)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:168)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:144)
at org.geoserver.filters.FlushSafeFilter.doFilter(FlushSafeFilter.java:42)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:168)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:144)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:168)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:144)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:168)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:482)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:130)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:660)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:346)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:396)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:937)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1791)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1190)
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63)
at java.base/java.lang.Thread.run(Thread.java:842)
Caused by: javax.xml.transform.TransformerException: java.lang.RuntimeException: Can’t get the id for a composite featurecollection; you need to identify the consituent collections directly.
at java.xml/com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:789)
at java.xml/com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:395)
at org.geotools.xml.transform.TransformerBase$Task.run(TransformerBase.java:291)
at org.geotools.xml.transform.TransformerBase.transform(TransformerBase.java:125)
at org.geotools.xml.transform.TransformerBase.transform(TransformerBase.java:107)
at org.geoserver.csw.response.MetaDataResponse.transformResponse(MetaDataResponse.java:35)
… 100 more
Caused by: java.lang.RuntimeException: Can’t get the id for a composite featurecollection; you need to identify the consituent collections directly.
at org.geoserver.feature.CompositeFeatureCollection.getID(CompositeFeatureCollection.java:68)
at org.geotools.data.DataUtilities.visit(DataUtilities.java:2805)
at org.geoserver.feature.CompositeFeatureCollection.accepts(CompositeFeatureCollection.java:74)
at org.geoserver.csw.response.AbstractRecordTransformer$AbstractRecordTranslator.encodeRecords(AbstractRecordTransformer.java:124)
at org.geoserver.csw.response.AbstractRecordTransformer$AbstractRecordTranslator.encode(AbstractRecordTransformer.java:112)
at org.geotools.xml.transform.TransformerBase$XMLReaderSupport.parse(TransformerBase.java:1165)
at java.xml/com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transformIdentity(TransformerImpl.java:693)
at java.xml/com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:780)
… 105 more

Hi Jive.

Don’t want to push it too hard,
but i have a similar problem in “full” mode when for the layer “USA Population”
(witch have a shape file store) i define a “Feature catalog identifier” AND
i auto generate the “Feature attributes”

Still taliking about sample data here.

Once again, thanks for your time.

Oh you are not pushing, I have never worked on the CSW service myself, and will not be starting today :slight_smile: indeed I have not paid enough attention to CSW to know who usually works on it and is comfortable with the code.

What you can do now is collect this for the issue tracker.

Good job hunting down where the problem occurred.